diff --git a/apps/control-station/src/components/laboratory/LaboratoryPresentation.tsx b/apps/control-station/src/components/laboratory/LaboratoryPresentation.tsx index 7502635..1349226 100644 --- a/apps/control-station/src/components/laboratory/LaboratoryPresentation.tsx +++ b/apps/control-station/src/components/laboratory/LaboratoryPresentation.tsx @@ -53,7 +53,7 @@ export const LABORATORY_REPORT_TEMPLATE_VERSION = const EXECUTION_LABELS: Record = { deterministic: "Детерминированный", - "ai-inference": "AI inference", + "ai-inference": "AI Inference", hybrid: "Гибридный", }; diff --git a/apps/control-station/src/core/observatory/aiComposition.ts b/apps/control-station/src/core/observatory/aiComposition.ts index 1c71e2a..14739c0 100644 --- a/apps/control-station/src/core/observatory/aiComposition.ts +++ b/apps/control-station/src/core/observatory/aiComposition.ts @@ -177,7 +177,7 @@ export async function renameAICompositionRunProjection( displayName: string, ): Promise { if (!/^ai-composition-[a-f0-9]{64}$/.test(runId)) { - throw new Error("Некорректная идентичность результата AI inference."); + throw new Error("Некорректная идентичность результата AI Inference."); } const normalized = displayName.trim(); if (!normalized || normalized.length > 160) { @@ -193,19 +193,19 @@ export async function renameAICompositionRunProjection( }); const body = await bodyOf(response); if (!response.ok) throw apiError(body, response.status); - const row = record(body, "результат AI inference"); + const row = record(body, "результат AI Inference"); exactKeys(row, ["display_name", "run_id", "schema_version"]); if ( row.schema_version !== "missioncore.observatory-ai-composition-run-projection/v1" || row.run_id !== runId || row.display_name !== normalized - ) throw new Error("Сервер не подтвердил переименование результата AI inference."); + ) throw new Error("Сервер не подтвердил переименование результата AI Inference."); return normalized; } export async function deleteAICompositionRunProjection(runId: string): Promise { if (!/^ai-composition-[a-f0-9]{64}$/.test(runId)) { - throw new Error("Некорректная идентичность результата AI inference."); + throw new Error("Некорректная идентичность результата AI Inference."); } const response = await fetch(`/api/v1/observatory/ai-composition-runs/${encodeURIComponent(runId)}`, { method: "DELETE", diff --git a/apps/control-station/src/core/observatory/catalogMutations.ts b/apps/control-station/src/core/observatory/catalogMutations.ts index c7d30ef..6efd498 100644 --- a/apps/control-station/src/core/observatory/catalogMutations.ts +++ b/apps/control-station/src/core/observatory/catalogMutations.ts @@ -96,7 +96,7 @@ export async function deleteObservatoryLabProjection( headers: { Accept: "application/json" }, signal, }, - "Не удалось удалить лабораторный результат из Обсерватории.", + "Не удалось удалить лабораторный результат из AI Inference.", ); const body = await responseBody(response); if (!response.ok || response.status !== 204) { @@ -132,7 +132,7 @@ function admittedProjectionId(binding: ObservatoryRecordedRunBinding): string { || !SAFE_SESSION_ID.test(sessionId) ) { throw new ObservatoryCatalogMutationError( - "Выбранный результат не допущен к изменению каталога Обсерватории.", + "Выбранный результат не допущен к изменению каталога AI Inference.", ); } return sessionId; diff --git a/apps/control-station/src/core/observatory/useObservatoryCatalog.ts b/apps/control-station/src/core/observatory/useObservatoryCatalog.ts index b79b551..6197a36 100644 --- a/apps/control-station/src/core/observatory/useObservatoryCatalog.ts +++ b/apps/control-station/src/core/observatory/useObservatoryCatalog.ts @@ -39,7 +39,7 @@ type ObservatoryCatalogMutationDraft = function errorMessage(error: unknown): string { return error instanceof Error && error.message.trim() ? error.message - : "Каталог Обсерватории недоступен."; + : "Каталог AI Inference недоступен."; } function isAbortError(error: unknown): boolean { diff --git a/apps/control-station/src/productModel.ts b/apps/control-station/src/productModel.ts index 69befc1..8020c2d 100644 --- a/apps/control-station/src/productModel.ts +++ b/apps/control-station/src/productModel.ts @@ -170,9 +170,9 @@ export const workspaces: WorkspaceDefinition[] = [ { id: "observatory", root: "polygon", - label: "Обсерватория", - title: "AI inference", - eyebrow: "ТЕСТОВЫЙ КОНТУР / ОБСЕРВАТОРИЯ", + label: "AI Inference", + title: "AI Inference", + eyebrow: "ТЕСТОВЫЙ КОНТУР / AI INFERENCE", description: "Сессии и квалификация без доступа к управлению.", icon: "eye", kind: "observatory", diff --git a/apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx b/apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx index 30f5589..db966aa 100644 --- a/apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx +++ b/apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx @@ -165,7 +165,7 @@ function compositionProducedEvidence( function mutationErrorMessage(error: unknown): string { return error instanceof Error && error.message.trim() ? error.message - : "Не удалось изменить лабораторный результат в Обсерватории."; + : "Не удалось изменить лабораторный результат в AI Inference."; } function evidenceConfigurationLabel( @@ -276,12 +276,12 @@ function aiJobStageDetail( return "Не удалось запустить модель. Конфигурацию можно отправить повторно"; } if (job.publication.state === "failed") { - return "Результат рассчитан, но не сохранён в Обсерватории"; + return "Результат рассчитан, но не сохранён в AI Inference"; } if (job.state === "succeeded") { if (job.publication.state === "pending") return "Завершаем сохранение результата"; if (job.publication.state === "not-required") return "Публикация результата не требуется"; - return "Результат сохранён в Обсерватории"; + return "Результат сохранён в AI Inference"; } if (!progress) { return "Готовим конфигурацию и место в очереди"; @@ -862,7 +862,7 @@ export function ObservatoryWorkspace({ {run.state === "ready" ? ( <> openCompositionDelete(run)} > @@ -952,7 +952,7 @@ export function ObservatoryWorkspace({ {evidence.recordedRun ? ( <> openDelete(evidence)} > @@ -1094,7 +1094,7 @@ export function ObservatoryWorkspace({

Будут удалены только каталожная проекция {deleteTarget?.label ?? compositionDeleteTarget?.displayName ?? compositionDeleteTarget?.presentation.configurationLabel} - {" "}и её отображаемое название в Обсерватории. + {" "}и её отображаемое название в AI Inference.

Исходная сессия, запечатанный лабораторный результат и файлы доказательств @@ -1177,7 +1177,7 @@ export function ObservatoryWorkspace({ ) : null} ) : null} - confirmLabel="Удалить из Обсерватории" + confirmLabel="Удалить из AI Inference" pendingLabel="Удаляем…" danger onClose={() => { diff --git a/apps/control-station/test/observatoryCatalogMutations.test.mjs b/apps/control-station/test/observatoryCatalogMutations.test.mjs index aeaf9e3..9c67628 100644 --- a/apps/control-station/test/observatoryCatalogMutations.test.mjs +++ b/apps/control-station/test/observatoryCatalogMutations.test.mjs @@ -114,10 +114,10 @@ test("Observatory mutations reject response drift and preserve API detail", asyn ); await assert.rejects( deleteObservatoryLabProjection(binding, { - fetcher: async () => Response.json({ detail: "Проекция не принадлежит Обсерватории." }, { status: 409 }), + fetcher: async () => Response.json({ detail: "Проекция не принадлежит AI Inference." }, { status: 409 }), }), (error) => error instanceof ObservatoryCatalogMutationError && error.status === 409 - && error.message === "Проекция не принадлежит Обсерватории.", + && error.message === "Проекция не принадлежит AI Inference.", ); }); diff --git a/apps/control-station/test/observatoryWorkspace.test.mjs b/apps/control-station/test/observatoryWorkspace.test.mjs index a1d8004..ba50dc8 100644 --- a/apps/control-station/test/observatoryWorkspace.test.mjs +++ b/apps/control-station/test/observatoryWorkspace.test.mjs @@ -34,9 +34,9 @@ test("Observatory is the third independent Polygon workspace", () => { { id: "observatory", root: "polygon", - label: "Обсерватория", - title: "AI inference", - eyebrow: "ТЕСТОВЫЙ КОНТУР / ОБСЕРВАТОРИЯ", + label: "AI Inference", + title: "AI Inference", + eyebrow: "ТЕСТОВЫЙ КОНТУР / AI INFERENCE", description: "Сессии и квалификация без доступа к управлению.", icon: "eye", kind: "observatory", @@ -200,7 +200,7 @@ test("Observatory rename and delete use admitted projection mutations and canoni assert.match(workspace, /[\s\S]*Сохранить/); - assert.match(workspace, / Срез 2026-09-05: этап временно зафиксирован владельцем. Текущая фактическая +> архитектура, ограничения и состояние приёмки описаны в +> [AI Inference](audits/2026-09-05-ai-inference-architecture.md) и отдельной карте +> Ops / MISSION CORE. Ниже сохранена история маршрута; старые «следующие шаги» +> не означают поручение автоматически продолжать запуск или мигрировать legacy LAB. ## ЕДИНСТВЕННЫЙ ТЕКУЩИЙ МАРШРУТ — 2026-09-03, модульное решение diff --git a/docs/adr/0051-modular-observatory-profiles.md b/docs/adr/0051-modular-observatory-profiles.md index 8a8ce2e..3b15d2d 100644 --- a/docs/adr/0051-modular-observatory-profiles.md +++ b/docs/adr/0051-modular-observatory-profiles.md @@ -2,6 +2,13 @@ Date: 2026-09-03. Owner-approved target; the first local modular vertical slice is installed. +Current implementation snapshot (2026-09-05): [AI Inference architecture](../audits/2026-09-05-ai-inference-architecture.md). +The owner has temporarily frozen this stage; user acceptance remains incomplete. +This ADR describes the target boundaries. The snapshot explicitly distinguishes +the implemented setup mapping and source/result reuse from the not-yet-wired +general DAG executor and per-node cache. The product name is now AI Inference; +technical Observatory identifiers remain compatible. + ## Decision and supersession A reusable module is an independently packaged Docker image for a model or a diff --git a/docs/audits/2026-09-05-ai-inference-architecture.md b/docs/audits/2026-09-05-ai-inference-architecture.md new file mode 100644 index 0000000..ce09c68 --- /dev/null +++ b/docs/audits/2026-09-05-ai-inference-architecture.md @@ -0,0 +1,289 @@ +# AI Inference — принципы работы и фактическая архитектура + +Срез на 5 сентября 2026 года. Репозиторий MISSION CORE, ветка `main`, исходный код аудита `e56eb42507d005cc372ac4a53785a080b116e227`. Изменения этого среза: терминология интерфейса и фиксация архитектуры. Исполнитель, модели, очередь, Rerun и способы обмена данными не рефакторились. + +## 01. Решение и границы закрытия + +AI Inference — текущий лабораторный путь применения выбранной AI-конфигурации к сохранённой физической записи и просмотра сохранённых доказательств. Раздел находится в LAB приложения Mission Core. Название «Обсерватория» больше не используется в текущем пользовательском интерфейсе. Технические `observatory` в URL, схемах, именах Python/TypeScript, Docker labels и старых evidence сохраняются для совместимости. + +По решению владельца этот этап временно зафиксирован. Завершены архитектурный срез и консолидация контекста; пользовательская приёмка ещё не завершена. Это не статус production-ready, не доказательство real-time и не разрешение на управление транспортом. Поля `actuation_allowed`, `commands_enabled`, `navigation_or_safety_accepted`, `production_accepted` у действующих portable definitions имеют значение false. + +Новые эксперименты строятся через этот путь. Старые LAB V1/M4.x и их приложения не становятся основой новых пользовательских поверхностей. Их результаты, код квалификации и происхождение алгоритмов сохраняются как история. Использование действующего TGS executor, выросшего из M4.9, не требует возвращать старый интерфейс лаборатории. + +Worker выключен. В этом аудите его не включали, Docker daemon на нём не опрашивали, ничего не устанавливали и не запускали. Факты разделены на код и текущую конфигурацию Core, локальный сохранённый каталог/журнал, исторические измерения и непроверенные возможности. + +## 02. Что является источником правды + +Для текущей реализации первичны `config/observatory-ai-modules.json`, `config/observatory-portable-run-definitions.json`, `config/observatory-worker-runtime-candidates.json`, `config/observatory-domain-ontology.json` и соответствующие исполнители в `src/k1link/observatory/`. Наличие записи `executor.state=ready` означает сохранённую регистрацию executor identity, а не работающую сейчас машину. + +Машинный срез: [2026-09-05-ai-inference-evidence.json](2026-09-05-ai-inference-evidence.json). В нём сохранены каталожные identities, ресурсные профили, текущая композиция и отобранные поля локальных jobs. Снимок не содержит ключей доступа, исходного видео, облаков, весов моделей и полных runtime-логов. + +Связанные решения: [ADR 0051](../adr/0051-modular-observatory-profiles.md), [история маршрута](../OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md), [handoff 3 сентября](../../experiments/perception/OBSERVATORY_MODULAR_HANDOFF_2026-09-03.md), [runbook Worker](../runbooks/OBSERVATORY_PORTABLE_WORKER_006.md). Старые слова CURRENT/«следующий шаг» в исторических отчётах не являются новыми поручениями и не отменяют этот срез. + +Ops MISSION CORE: #75 «AI Inference · Принципы работы и архитектура» (`e5768b6c-0817-4e9e-a786-f9167586c7dc`) с полным содержанием этого отчёта; #73 — история перехода к модульным профилям; #74 — подробный реестр кастомизации Rerun; #66 — канон Rerun; #9 — история AI Worker; #65 — историческая LAB V1. Новая карта не стирает свидетельства ошибок в старых картах. Статус Done у #75 означает завершение документирования среза; открытые пункты пользовательской/target-приёмки перечислены в checker и ниже. + +## 03. Основные сущности и их владельцы + +| Сущность | Значение и владелец | +|---|---| +| Физическая сессия | Запись оборудования: видео, LiDAR, pose/trajectory, временные шкалы, калибровка и provenance. Каталог сессий Core; не результат AI. | +| Версия модуля | Модель либо связанная алгоритмическая функция с точными image/code/model/contract identities, входами и выходами. Реестр модулей и sealed package. | +| CompositionSpec | Неизменяемый проверенный набор версий, параметров, зависимостей и execution policy; не привязан к одной конкретной записи. | +| LAB / composition run | Применение композиции к точному source snapshot; связывает состав, member jobs и опубликованные результаты. | +| Recorded job / attempt / lease | Единица выдачи работы и её конкретное владение исполнителем. Durable очередь Core, claim token и generation fencing. | +| Portable result | Неизменяемые артефакты и метаданные доказательства, identities, покрытие и authority. Публикуются на Core. | +| LAB display profile | Изменяемое оформление просмотра, отдельно от расчётной конфигурации и raw evidence. Хранится на Core по result_id. | +| Viewer session | Временное положение камеры, FOLLOW, включённые слои и пропорции окон. Не следует отождествлять с сохранением всего LAB profile. | +| Worker / installed executor | Доверенный исполнитель, которому разрешены конкретные версии packages и ресурсы. Не произвольная удалённая shell-машина из UI. | + +Изменение цвета или размера точек не пересчитывает модель. Переименование отображаемой LAB не меняет immutable composition/result identity. Удаление из пользовательского каталога не следует трактовать как переписывание доказательства или автоматический Docker prune. + +## 04. Пользовательский путь + +Оператор выбирает сохранённую сессию. Core сообщает доступные каналы и применимость setup. Кнопка «Сконфигурировать AI-слой» открывает выбор по функциональным группам. UI получает каталог с сервера; он не извлекает возможности из свободного названия LAB. + +Выбранные модули проходят проверку зависимостей и совместимости источника. Сохраняется точная композиция. Core создаёт либо использует уже существующие подходящие member jobs/results, показывает их совместный статус, а после публикации открывает связанный визуальный разбор. Повторный просмотр готовой LAB не должен запускать inference. + +Название строки состоит из реальных конфигурационных значений. Название исходной сессии в строках списка не дублируется; в заголовке открытого результата сохраняется полный контекст. Дата и время расчёта, сортировка по времени, просмотр, переименование и удаление доступны в каталоге. Прогресс относится к активной обработке; готовая строка не должна навсегда оставаться шкалой 100%. + +Глобальный смысл состояний: инициализация → передача на сервер → расчёт. Внутри расчёта могут быть подготовка камеры/LiDAR, загрузка модели, собственно inference и сборка результата. Эти подэтапы должны называться по фактической операции. Процент очереди/пакета нельзя интерпретировать как долю кадров модели или обещание точного ETA. + +## 05. Каталог модулей и зависимости + +| Модуль | Входы → выходы | Текущее назначение | +|---|---|---| +| camera-source | source.camera → camera.frames | Служебная подготовка камеры, добавляется зависимостью. Не отдельный пользовательский эксперимент. | +| DDRNet-39 · GOOSE | camera.frames → segmentation.mask | Семантическая сегментация выбранной версией DDRNet. | +| EoMT Large · Cityscapes | camera.frames → segmentation.mask | Альтернативный провайдер сегментации. | +| RF-DETR Large | camera.frames → detections.2d | Детекция объектов; текущий package содержит TensorRT engine. | +| Дистанция до объектов | detections.2d + source.calibration + source.lidar + source.pose → objects.ranged | Сопоставление детекций с калиброванными LiDAR/pose; собственных обученных весов нет. | +| TRAVEL TGS | source.calibration + source.lidar + source.pose → geometry.costmap + geometry.ground | Геометрическая обработка, ground/costmap; без отдельной ML-модели. | + +В новой композиции допускается не более одного провайдера в группе. DDRNet и EoMT — альтернативы, не два одновременно выбранных segmentation provider. Зависимости включаются детерминированно; range требует RF-DETR. Циклы, неоднозначные провайдеры и пустой недопустимый граф отвергаются. + +Группы motion и policy присутствуют в модели каталога, но в текущем реестре пусты. Это не доказательство установленных модулей движения или управления. Полный исторический perception prototype имел более широкий состав; его нельзя автоматически приписать текущему UI. + +Разрешённые параметры расчёта ограничены версией модуля: у текущих stateless AI modules cadence допускает 1; у TGS causal history-seconds допускает 1 и действует reset-at-source-start. Это вычислительные контракты. Пользовательский slider накопления SLAM 0–500 секунд относится к отображению и не увеличивает расчётную историю TGS. + +## 06. Граф: декларация и реальное исполнение + +`modular_composition.py` проверяет capabilities, identities, параметры и топологический порядок. `modular_composition_store.py` сохраняет неизменяемую спецификацию. Execution policy текущих композиций: `recorded-observation-only`, `max_parallel_nodes=1`. `composition_runs.py` связывает source, composition и результаты запуска. + +Важная граница реализации: `web/modular_observatory_api.py` переводит известный набор модулей в заранее поддержанные setup IDs. Это работающий ограниченный композитор, но ещё не универсальный runtime, который исполняет произвольный DAG из любого числа новых Docker-узлов под одной lease. + +Текущие AI setup IDs: `ai-segmentation-ddrnet-v1`, `ai-segmentation-eomt-v1`, `ai-detection-rf-detr-v1`, `ai-range-object-distance-v1`; геометрия — `m49-tgs-portable-v2`. Когда выбран range, отдельный standalone RF-DETR job не создаётся: RF-DETR выполняется внутри range package. Поэтому полная выбранная конфигурация DDRNet + RF-DETR + range + TGS даёт три member jobs, а не четыре. + +Подходящий ранее созданный non-failed job может быть использован снова; опубликованный member result связывается с новой композиционной проекцией. Точная повторная отправка композиции с существующей допустимой работой не должна размножать расчёты; конфликт сообщает API. Failed execution допускает повторную попытку по действующему маршруту. + +Очередь отдельного job durable. Создание группы member jobs и запись composition-run projection не являются одной общей SQL-транзакцией универсального DAG. Нельзя обещать атомарность всей композиции на основании транзакционности очереди. Полноценное расширение scheduler и его аварийная приёмка остаются отдельной работой. + +## 07. Схема коммуникации + +```mermaid +flowchart LR + UI[Web UI: AI Inference] -->|same-origin HTTP| Core[Mission Core API :8000] + Core --> Catalog[Sessions / composition / ontology projection] + Core --> Queue[Durable recorded queue] + Worker[Installed Worker agent] -->|claim / renew / progress / terminal| Core + Core -->|verified source package| Worker + Worker -->|local Docker API| Steps[Sequential compute containers] + Steps -->|sealed output| Worker + Worker -->|manifest + verified member uploads| Core + Core --> Publish[Publication / artifact store / result catalogue] + Publish -->|base + overlay + profile| Viewer[Official Rerun in Web UI] +``` + +Браузер обращается к Core, не управляет Docker и не соединяется напрямую с Worker. Worker забирает работу у Core по HTTP pull-протоколу. Нынешний recorded-путь не отправляет каждый кадр через отдельный браузерный запрос или gRPC-поток: исходный пакет передаётся, вычислительные шаги работают с локальными входами, выход затем публикуется обратно. + +Live telemetry оборудования — отдельный контур. Telegraf → MQTT → normalizer → Timescale → Core/System не заменяет HTTP job protocol. Свежая телеметрия не доказывает успешную публикацию LAB, а сохранённая LAB остаётся читаемой без работающего Worker. + +## 08. Адресация, туннель и доверие + +Файлы: `worker_http_transport.py`, `worker_tunnel_launchd.py`, `worker_container_proxy.py`, `worker_agent.py`. Текущий Core слушает локально `127.0.0.1:8000`. На Mac управляется SSH reverse tunnel через alias `mission-gpu`: `-R 127.0.0.1:18080:127.0.0.1:8000`, с BatchMode, ExitOnForwardFailure и keepalive. + +Внутри agent container клиент обращается к loopback proxy :18080. Proxy направляет запросы на `host.docker.internal:18080`; на Windows host это loopback endpoint SSH-туннеля к Core. Следовательно, loopback HTTP защищён транспортом SSH на межмашинном участке. Здесь нет утверждения о публичном HTTP-порту Worker без защиты. + +Transport принимает HTTPS либо HTTP только для loopback, передаёт Bearer auth и contour identity. Текущее исполнение привязано к `worker-006`. Два HTTP connection slots оставляют возможность служебного обмена при передаче пакета. Ключи, значения credentials и файлы с ними намеренно не входят в карту. + +Это конкретная топология Mac Core ↔ Windows/Docker Desktop Worker. Наличие протокола не означает, что имя другого компьютера можно просто подставить в UI. Linux host networking и `host.docker.internal`, доверие SSH, токен, contour binding и установленный release потребуют согласованной адаптации. Реализация регистрации нового Worker в этот этап не входит. + +## 09. Lease, очередь и восстановление + +Worker вызывает `/api/v1/worker/observatory/recorded-jobs/claims` с claim schema v3 и перечнем поддержанных executor identities. При отсутствии работы получает 204. Затем идут start, lease renew, progress и terminal; upload result package имеет отдельные plan/member/complete операции. + +Core сверяет source/definition/executor/resource/result contracts. Claim token и generation защищают от публикации запоздалым исполнителем. UI не может передать произвольный image, shell command, mount или network target через job. Вычислитель получает выбранный установленный package. + +Ресурсные профили текущего Worker закрепляют последовательную работу на NVIDIA RTX 4090 и concurrency=1. Это не доказательство параллельного исполнения всех модулей. Политика допускает преимущество live-работы над recorded; текущие тяжёлые recorded jobs non-checkpointable. После вытеснения/ошибки до sealed результата нельзя обещать продолжение ровно с последнего кадра. + +Worker имеет ограниченное восстановление транспортных ошибок и heartbeat; Core хранит durable job/publication state. Если вычисление завершено и результат запечатан, повтор публикации не должен повторять inference. Если результат ещё не запечатан, повторный запуск может начать обработку заново. История failed attempts сохраняется, а не становится фиктивным успехом при появлении следующего успешного результата. + +## 10. Docker: что действительно упаковано + +Нужно различать agent image, compute module image, installed package и реально запущенный контейнер. Agent опрашивает Core и управляет этапами. Compute container выполняет ограниченный шаг. Package закрепляет последовательность, изображения, assets, команды и contracts. Контейнерный ID — конкретный экземпляр на машине; его текущего значения этот offline-аудит не устанавливает. + +Dockerfiles находятся в `experiments/perception/worker/observatory_portable/`: `Dockerfile.ai-module-camera-source`, `Dockerfile.ai-module-ddrnet`, `Dockerfile.ai-module-eomt`, `Dockerfile.ai-module-rf-detr`, `Dockerfile.ai-module-object-distance`, файлы installed-lab worker agent и специализированного M4.9 executor. Builder: `scripts/build_modular_ai_worker_release.py`. Исполнение: `installed_lab_packages.py`, `installed_lab_package_runner.py`, `modular_installed_package_steps.py`, installed worker service/container main; для TGS — `m49_worker_service.py` и соответствующий main. + +Модульность сейчас прежде всего логическая и контрактная. Camera-source использует private base `ndc/mission-core-installed-lab-v1-eomt-step:ee0efdd9af72`; DDRNet — `ndc/mission-core-installed-lab-v1-ddrnet-step:439127908dba`; RF-DETR и object-distance опираются на `ndc-k1-perception-ddrnet39-rfdetr-tgs:stage1-joint-20260901`. Поэтому нельзя описывать каждый модуль как уже минимальный полностью независимый образ без наследованных окружений. + +Некоторые FROM закреплены tag, хотя установленный release и готовые images проверяются по SHA. Для воспроизводимой чистой пересборки нужны именно соответствующие private bases, внешние assets и версии инструментов; один текст Dockerfile без них недостаточен. Отдельные conda/Python/model environments внутри compute stages остаются частью переносимого комплекта. + +`ModuleSpec.docker_name` и ownership labels задают идентичность/наименование, а не доказывают наличие отдельного постоянно работающего сервиса на каждый модуль. В частности, TRAVEL TGS в текущем пути использует квалифицированный специализированный executor. Старые контейнеры LAB V1/других исследований не удалялись этой фиксацией. + +## 11. Зафиксированные образы, модели и releases + +SHA ниже взяты из текущих versioned registries; это конфигурационный срез, не сегодняшняя команда docker inspect на выключенном Worker. + +| Модуль | Compute image SHA-256 | +|---|---| +| camera-source | da926459aee0a841bbdfaf80a0eb5fbead354c56794d1f3384eeba66d0a49e00 | +| DDRNet | 489fc7d1157fd0f1cd1d82e06a15737b7b2aaaf72b2ddb2aca2992b91a97488e | +| EoMT | 5b770178e4a5c8fbe8f8ddab3b83a598973dbe103b669851110b11a0918ab846 | +| RF-DETR | 2b8b44be8e9ee4060aa6997fc4c025ad7120f37ecd720a9e59b5e02ac6c90f66 | +| object-distance | 69d68f64981b41e5bcce1e642433e3d466b88c51942a5ba3aec9180d8ed04263 | +| TRAVEL TGS | f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3 | + +Веса DDRNet: `b99c2838051bcd7b092fd3970aa62a77d5c0bbb809c9b9afb2ff4b0ebdaa4ee6`. EoMT weights: `c265da9a74f58f5c3f4826d23ca4ca78beac0b106cca5842beca61580de5b782`. RF-DETR TensorRT engine: `b8a40b3580edff001ec9680de68707242294ff590ab296000fae371f1083f695`. TensorRT engine не следует считать универсальным переносимым checkpoint для любого GPU/runtime. + +У четырёх новых AI setup текущий executor image SHA `7a1d425b4678dcade7d7d6ffd14733d639a4df29f45e1759ba4c512e930da8ab`, release ID `ai-modular-installed-package-v1`, release SHA `97bfe743689766285b22627c4020d10df7949ef1f4546ef904dccb9ca4c6f721`. Все привязаны к worker-006. + +TGS definition v3 использует image `f9278ab2…`, release `m49-tgs-portable-executor-v1`, release SHA `c5b0670d943fe0452ef4bbfbc144ab2439a1a674f9ef164798ad9f8b1ecc29fa`. Старая совместная LAB V1 definition v2 с executor `5ad7d95b…` и release `66785862…` остаётся в совместимом реестре; она не заменяет новые modular setups. + +Важно сохранять provenance каждого результата: успешно опубликованный DDRNet member произведён предыдущим release `ecbb0edc1c4c3708329247a2210ef98dfa776bf948974e778ba6d131ad17a924`, хотя image agent совпадает. Range member использует текущий `97bfe743…`. Совпадение agent image не означает одинаковость sealed package. Каталоги `.runtime/*v8/v9/v10` — локальные артефакты сборки; наибольший номер папки не является источником истины о фактически установленном release. + +## 12. Ресурсы и изоляция compute + +Installed agent — доверенный оркестратор с доступом к Docker API/socket. Его нельзя описывать как полностью непривилегированный компонент без влияния на host. + +Дочерние вычислительные контейнеры запускаются с ограничениями package runner: `network=none`, read-only root filesystem, drop ALL capabilities, no-new-privileges, без privileged mode. Входы, модели и проверенные code assets монтируются read-only; writable output ограничен каталогом шага. Заданы RAM/MemorySwap, CPU NanoCpus, Pids, SHM/tmpfs и GPU DeviceRequests. Точное значение бюджета зависит от resource profile/package, а не от свободного UI ввода. + +GPU device admission не является жёсткой квотой VRAM. На имеющейся конфигурации действует последовательный допуск. Обещание безопасной параллельной работы N разных GPU моделей требует отдельного замера памяти и admission policy. + +Историческая инвентаризация 3 сентября сообщала 11 containers, 7 running/4 stopped, 80 images, 9 volumes. Эти числа сохранены в архиве, но не являются текущим состоянием выключенного Worker. Другие исследования/сервисы, включая Gaussian и retained LAB packages, не следует автоматически считать зависимостями AI Inference или удалять по этой карте. + +## 13. Передача данных и фактический кэш + +Source package строится из конкретной сессии и проверенных members. Проверяются digest, размер и допустимость путей. `worker_source_cache.py` содержит source CAS (`.source-cas-v1`), который позволяет повторно использовать совпадающие исходные bytes. Кэш не разрешает смешивать похожие записи или произвольные версии калибровки. + +Холодная подготовка остаётся существенной: загрузка camera archive завершается до extraction; декодирование/согласование камеры и LiDAR может предшествовать модельному этапу. Model-neutral camera-source убирает логическую зависимость подготовки от выбора segmentation, но не доказывает, что каждый отдельный job уже использует один готовый общий prepared-frame cache. + +`portable_result_cache.py` и composition member reuse работают на уровне совпадающих сохранённых результатов. Чтение уже опубликованного результата не должно требовать GPU Worker. + +Особенно важная проверка: `modular_node_cache.py` и `node_input_identity` существуют и покрыты тестами, но поиск production call sites обнаруживает определения и тесты без подключения `ModularNodeCache` к основному исполнителю. Поэтому универсальный кэш каждого узла композиции пока не заявляется работающей функцией. Старое намерение «каждый модуль считается один раз для всех LAB» ещё не равно реализации. + +## 14. Результат и публикация + +Результат связывает source snapshot, exact definition, module/package/model identities, временное покрытие и артефакты. `portable_artifact_transport.py` принимает manifest и members, `portable_result_publisher.py` создаёт опубликованную проекцию, `portable_publication_reconciler.py` доводит durable publication/outbox до согласованного состояния. + +Результат проверки/расчёта и построенный для Rerun cache — разные артефакты. Смена renderer identity может потребовать перестроить производный cache; она не должна переписать исходные sealed results. Недоступный или неподходящий source должен давать явное состояние, а не демонстрационные точки вместо реальных данных. + +Готовность полной LAB означает доступность требуемых member results по composition projection. Она не делает timestamps всех member jobs одинаковыми и не доказывает, что весь состав был вычислен одним совместным запуском. Сохранённая точная конфигурация важнее свободного названия строки. + +## 15. Что действительно есть в текущем каталоге + +Проверено через локальный Core API 5 сентября, без подключения Worker. Источник: `20260828T130511Z_viewer_live`, имя RAVNOVES004TREE, XGRIDS LixelKity K1, capture profile `xgrids-k1.viewer-live.fw-3.0.2.v1`, длительность 808.779 секунды (13:28.779). + +В текущей проекции есть ready composition `ai-composition-33389babab33b801e8892f7b991683487eef2deea507486e52569fe943082e4b`, composition SHA `230396b858b09eea3d1d3a190c5e32d1d5e379da0058d32341026937fbb5cf24`. Создана 4 сентября в 06:59:35 UTC. Состав: DDRNet, RF-DETR, object-distance, TGS. Связаны три опубликованных member result; в UI также доступны отдельные сохранённые DDRNet и TGS строки. + +| Member | Job | От создания job до публикации, UTC | +|---|---|---| +| DDRNet | observatory-run-ef3c14a64fca4d5a8674df82a5a0fca2 | 04.09 03:57:16.996 → 04:26:44.704; 29 мин 27.708 с | +| TRAVEL TGS | observatory-run-b230216709dc4c59bc56c98c7e329bf1 | 03.09 08:08:03.013 → 08:31:39.776; 23 мин 36.763 с | +| object-distance, включая RF-DETR | observatory-run-185e25280d58472ab8b4a0245a35c888 | 04.09 06:29:36.181 → 07:00:02.263; 30 мин 26.082 с | + +Result IDs: `ai-layer-ddrnet-7c6a79942683933390f5ff0ecf2c6da1867d40032e91303746a567198772ce5c`; `m49-tgs-portable-review-a09d2b4a07d103e4f3693ba746a51be2197214768774eabfded4f109ae80dce4`; `ai-layer-object-distance-05f3931621585c9ac32132bef8c7afa961cea317cc29def09a8312339f8421e4`. + +Это wall time конкретных успешных jobs, включая всё между enqueue и publication; это не model latency. Не надо складывать эти числа и называть суммой latency одного composition run: его members переиспользованы из разных дат. + +История по этой сессии и setup при запросе до 100 jobs: DDRNet — 7, из них 1 succeeded/published и 6 failed; range — 7, из них 1 succeeded/published и 6 failed; TGS — 4, из них 1 succeeded/published, 1 succeeded с publication not-required и 2 failed. У новых standalone EoMT и RF-DETR setup — 0 jobs для этой сессии. Ноль здесь не означает отсутствия модели или старых экспериментов; успешный standalone recorded прогон ими в этом срезе не подтверждён. Действующие failures не стираются итоговой готовностью одной LAB. + +## 16. Реальное покрытие и смысл измерений + +Полная длительность источника и фактическое покрытие результатов должны быть отдельными полями. Исторический TGS handoff для этой записи указывает 6830 camera anchors, 6811 LiDAR matches и 19 unobserved; processing schedule примерно 39.215–757.160 секунды внутри источника 808.779 секунды. Надпись «полный маршрут» не должна скрывать начальные/конечные непокрытые интервалы и отсутствующие наблюдения. + +В сохранённом TGS performance: candidate TGS p50=1.204 ms, p95=2.6075 ms, p99=3.2357 ms, max=4.651 ms. Более широкий stage wall: p50=17.676102 ms, p95=29.99172 ms, p99=36.24682261 ms, max=1269.499327 ms. Это разные границы измерения внутри алгоритма и обвязки; они не опровергают десятки минут enqueue→publish при подготовке записи. + +Для честного сравнения нужно сохранять source rate, coverage, cold/warm режим, hardware/runtime identity, sample count и границы: queue wait; source transfer; decode/align; warmup; model/algorithm compute; serialize/seal; result upload/publication; replay preparation. Нельзя вычитать p95 одной фазы из p95 другой и получать корректный p95 остатка. FPS визуального воспроизведения Rerun тоже не является inference FPS. + +Текущий recorded-first путь предназначен для воспроизводимых сравнений и сохранённых доказательств. Из имеющихся результатов не следует ни обещание полного real-time, ни утверждение, что модель сама считает один кадр две секунды. Долгие пользовательские ожидания из истории были реальными и должны оставаться частью performance backlog. + +## 17. Предыдущий streaming experiment и его результат + +Сохранены исследования `experiments/perception/worker/streaming_profile_stage1/`, [stage 1](../../experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md), [cross-host graph](../../experiments/perception/PERCEPTION_STREAM_STAGE2_CROSSHOST_GRAPH_2026-09-02.md), [control clock](../../experiments/perception/PERCEPTION_STREAM_STAGE2_CONTROL_CLOCK_2026-09-02.md), [TLS attribution](../../experiments/perception/PERCEPTION_STREAM_STAGE2_TLS_ATTRIBUTION_2026-09-02.md), [LAN route](../../experiments/perception/PERCEPTION_STREAM_STAGE2_LAN_ROUTE_2026-09-02.md). Подробные receipts также перенесены из Desktop в архив. + +Это отдельный resident perception prototype: DDRNet/RF-DETR, LiDAR/range, motion, TGS/costmap и policy stages, бинарный обмен gRPC/TLS и pacing источника 1×. Он не является текущим recorded HTTP worker protocol и не становится автоматически модулем motion/policy в сегодняшнем UI. + +Исторический joint image: `986dbe7126992359c69da0ddda674925a5efe8e3429a6d5f60765f9c9ad34a4e`, tag `ndc-k1-perception-ddrnet39-rfdetr-tgs:stage1-joint-20260901`. Использовались model/code mounts; это не полностью автономный образ. Конкретный приёмочный фрагмент: 32 released/accepted results с byte-exact доставкой; fresh scene outputs — 12. Эти числа нельзя заменять фразой «32 полностью свежих результатов сцены». + +На Worker локально compute→local receiver p95/p99 = 74.243/76.322 ms. Межмашинная граница Mac source-due→consumer-ready p95/p99 = 205.864/213.751 ms при gate 125 ms: FAIL. Min 86.598 ms, median 121.85 ms не превращают хвосты в PASS. Историческая проверка выявила Wi-Fi с обеих сторон и TCP tails 67.921–91.142 ms ниже приложения; это основание изучать сеть, а не основание объявить всё задержкой модели. Истощение VRAM в этом конкретном опыте не было доказано. + +Опыты показывают полезный compute budget и нерешённый end-to-end gate на тогдашней сети. Перенос resident runtime на будущий борт, совместимость другого GPU и абсолютный real-time не квалифицированы этим отчётом. Повторный streaming benchmark сейчас не запускался. + +## 18. Локальная онтология и связи с оборудованием + +В Mission Core уже есть предметная проекция: `config/observatory-domain-ontology.json` и `src/k1link/observatory/domain_ontology.py`. Она связывает transport/equipment/mount, capture profile, source session, module version/image, worker, composition, run/job/result, LAB view profile и layers/panes. + +Она обслуживает согласованные запросы планирования, dispatch, публикации и replay: точная подпись конфигурации, состав member results, доступные слои и готовность. Идентичности берутся из существующих реестров/хранилищ; это не конкурирующая база, самовольно переименовывающая raw evidence. + +Онтология отдельного NDC Platform repository не изменялась, runtime dependency на неё для AI Inference не добавлялась. Архитектурный принцип связанной модели применён локально. Формальное присутствие transport/equipment сущностей не равно готовой регистрации любого оборудования, универсальному драйверу RealSense или автоматическому конструктору 50 камер. + +## 19. Rerun: один runtime, локальные контролы и сохранение + +Полная самостоятельная карта: Ops #74 и [2026-09-05-rerun-customization-inventory.md](2026-09-05-rerun-customization-inventory.md), с [проверкой upstream](2026-09-05-rerun-upstream-evidence.json). В ней перечислены все действующие и архивные надстройки, точные файлы, хеши и upgrade gates. Здесь только роль в AI Inference. + +Используется официальный Rerun 0.36.3; установленные JS/WASM и Python SDK в предыдущем аудите побайтно сверены с upstream. Recorded viewer живёт в same-origin iframe, имеет один native renderer/store/clock. Камера и spatial — виды внутри общего viewer. Внешний SplitPane владеет разделением, контролы принадлежат своим секциям, native layout получает согласованную долю. Верхняя панель переносит не помещающиеся группы; refresh/fullscreen относятся к общему layout. + +Слои строятся из capabilities результата: фон КАМЕРА независим от segmentation и РАМОК; кнопка рамок зависит от detections; TGS от geometry evidence. Отключённый фон камеры не должен выключать остальные 2D layers. Один тип источника допускает одно окно. Сегодня реализованы camera/spatial и single-pane варианты, а не произвольное дерево из 50 камер. + +ИСХ. ТОЧКИ и ЛОК. SLAM сейчас используют одно sealed `/world/points`. Отличаются отображение/накопление и дополнительные trajectory controls; это не две независимые коллекции «математические» и «декоративные». Изменения размера/цвета не меняют raw/AI расчёт. + +Надстройка FOLLOW и восстановления eye использует прикладной журнал native gestures и blueprint. Это не официальный универсальный get-camera-pose API. Не все gestures покрыты: WASD, double-click/picking-fit, inertia могут расходиться с журналом. Такие ограничения явно оставлены в #74; этот документ не объявляет все пользовательские сценарии зума принятыми. + +Server-side LAB display profile сохраняет point_size, accumulation_seconds, color_mode, palette, show_grid, show_labels, show_camera_frustums отдельно от immutable result. Применение point size/накопления/цвета/grid подключено; show_labels и show_camera_frustums сохраняются, но визуально не подключены к текущему canonical LAB пути. Layer toggles, FOLLOW, eye и split ratio в этот durable profile не входят. + +Slider накопления 0–500 s и точный ввод конечного неотрицательного значения без верхнего product cap; размер slider 0.1–10 px, точный ввод ≥0.1 без верхнего cap. Закрытие настроек отправляет PUT; ошибка не должна блокировать закрытие и показывается компактным сообщением. Только успешная серверная запись подтверждает сохранение после очистки локального кэша. Сохранение в памяти/localStorage само по себе этого не доказывает. + +## 20. Переносимость — что возможно и чего ещё нет + +| Объект переноса | Реальное условие | +|---|---| +| Просмотр готовых LAB на другом Core | Перенести каталог, source/result artifacts, lineage и profiles с сохранением identities; обеспечить renderer/SDK и восстановление производных caches. Worker для просмотра не требуется. | +| Та же композиция на другой записи K1 | Источник обязан пройти admission по требуемым каналам, калибровке, media epoch/codec, геометрии и timestamps. Один совпавший label недостаточен. | +| GPU-модули на другом AI Worker | Нужны compatible CPU architecture/GPU/CUDA/TensorRT, exact images, private bases для rebuild, models/code assets, installed package, resource profiles и протокол связи. Не один docker load. | +| Worker с другим именем/contour | Сейчас имеются worker-006 bindings и проверки. Общая динамическая регистрация/автовыбор любого Worker не заявляется готовой. В эту задачу не входит. | +| Linux вместо Windows Docker Desktop | Нужна проверка network/host bridge, paths, mounts, GPU runtime и SSH topology; host.docker.internal нельзя молча считать одинаковым. | +| Новая модель | Требуются ModuleSpec, versioned image/contract, adapter/installed steps, setup projection, input/result verification, capability→viewer mapping и evidence. Сейчас UI не универсальный marketplace Docker images. | +| Другое оборудование / 50 камер | Нужны source adapters, calibration/time contracts, admission и расширение layout/ресурсной модели. Сущности онтологии дают место для этого, но не готовую реализацию. | +| Бортовой real-time | Resident prototype, recorded LAB и бортовая qualification — разные границы. Нужен отдельный измеренный deployment на выбранном target. | + +Переносимость достигнута в identities, пакетах, протоколах и сохранённых результатах. Привязки к Worker-006, K1 и имеющимся окружениям остаются конкретными. Утверждение «полностью независимо от host» сегодня было бы неточным. Изменять эти границы ради красивого отчёта без работающего Worker не стали. + +## 21. Архив Desktop без потери контекста + +Два относящихся к AI Inference документа перенесены побайтно в `docs/handoff/ai-inference-source-documents/` и снабжены [manifest.json](../handoff/ai-inference-source-documents/manifest.json). Это полные исходные тексты, включая ошибки, планы, замеры, списки Docker и последовательные обновления; не только краткий пересказ. + +| Исходный файл Desktop | Bytes | SHA-256 | +|---|---:|---| +| _MISSING_CORE_MODULAR_AUDIT_AND_PLAN_2026-09-03.md | 53637 | d6c201d083fbec4b1db031379b515ff821a09ccfa0cea62443e211a9d76cb1c2 | +| _MISSING_CORE_OBSERVATORY_DOCKER_LABS_FINAL_STATUS_2026-09-01.md | 330260 | 45e870700baddab8f31a2f0f0bfe1f9e99e8e73a490195c1e6a3beb5265e49ee | + +Другие документы на Desktop не объявляются перенесёнными этой картой. Исходники не удалялись автоматически. После публикации commit пользователь может удалить именно эти два оригинала: versioned копии и хеши остаются в репозитории, а их актуальная интерпретация — здесь и в Ops. + +Исторические указания из этих файлов не исполняются как команды. Раннее требование «весь профиль в одном монолитном образе» заменено ADR 0051. Историческое описание node cache как цели отделено от фактического отсутствия production wiring. Старые Docker inventories и streaming receipts датированы; не выдаются за результаты сегодняшнего запуска. + +## 22. Проверки этого изменения и открытые границы + +Для переименования выполнены архитектурные frontend tests (4 passed), полный frontend typecheck, полный unit suite (759 passed), production build и targeted Python tests `test_modular_observatory_api.py`/`test_observatory_setups.py` (22 passed). Изменения runtime поведения и новые вычислительные jobs в этом этапе не выполнялись. + +В открытом in-app browser обновлена сборка и пройден путь LAB → AI Inference. Новые sidebar label, eyebrow, title и aria-подсказки удаления подтверждены реальным UI. Проверены обычный и развёрнутый shell, три сохранённых строки с датами/действиями; открыта полная сохранённая конфигурация с камерой, DDRNet, рамками и TGS. Fullscreen самого результата и возврат по Escape проверены. Escape на shell сам по себе не меняет его состояние; это не объявляется успешным закрытием shell. Текущая задача не меняет политику Escape/диалогов. Реальная сохранённая конфигурация оставляется для просмотра владельцем. + +Срез временно закрыт по документации. Открыты: окончательная пользовательская приёмка навигации Rerun и настроек; два неподключённых display fields; полный native camera-state API вместо неполного gesture journal; универсальный multi-pane constructor; универсальное исполнение DAG/production node cache; новые Worker/оборудование и target CUDA qualification; end-to-end real-time gate и полноценные cold/warm phase metrics. Это границы текущего продукта, не скрыто выполненные пункты. + +При возобновлении работы исходная точка — этот срез, actual registry и конкретные new measurements. Legacy LAB приложения автоматически не возвращаются; неизвестные состояния выключенного Worker сначала проверяются после его появления. Любое следующее обновление Rerun проходит отдельно по карте #74. + +## 23. Изменённые файлы и эксплуатационная фиксация + +Переименование: `apps/control-station/src/productModel.ts`, `components/laboratory/LaboratoryPresentation.tsx`, `workspaces/observatory/ObservatoryWorkspace.tsx`, `core/observatory/{aiComposition,catalogMutations,useObservatoryCatalog}.ts` внутри frontend; `src/k1link/observatory/setups.py`, `src/k1link/web/{observatory_api,modular_observatory_api}.py`. Обновлены ожидания существующих `observatoryWorkspace.test.mjs` и `observatoryCatalogMutations.test.mjs`. Дизайн, identifiers, параметры расчёта и бинарные модели не изменены. + +Документация: этот отчёт, JSON evidence, README/manifest и две полные копии в `docs/handoff/ai-inference-source-documents/`; указатели текущего среза в ADR 0051 и историческом ExecPlan. Ops #75 создана как текущая архитектурная карта; #73 переименована в историческую карту с указателем #75 и сохранением всех прежних блоков. + +Production frontend bundle пересобран. Канонический локальный LaunchAgent `com.nodedc.mission-core.local` перезапущен из того же checkout для применения Python-текстов. `/api/health` на :8000 подтверждает operational=true, plugin runtimes 1/1, готовность источников и artifact store. Новый сервер на другом порту не создавался; удалённый Worker не запускался. Код и архив публикуются в main обычным commit/push без переписывания истории. Точный итоговый commit указывается в финальном блоке Ops #75. diff --git a/docs/audits/2026-09-05-ai-inference-evidence.json b/docs/audits/2026-09-05-ai-inference-evidence.json new file mode 100644 index 0000000..4ad35df --- /dev/null +++ b/docs/audits/2026-09-05-ai-inference-evidence.json @@ -0,0 +1,850 @@ +{ + "snapshot_date": "2026-09-05T06:51:04.590227+00:00", + "code_baseline": "e56eb42507d005cc372ac4a53785a080b116e227", + "worker_live_inspection": false, + "source_session_id": "20260828T130511Z_viewer_live", + "modules_registry": { + "schema_version": "missioncore.observatory-ai-module-registry/v1", + "modules": [ + { + "module_id": "camera-source", + "label": "Подготовка камеры K1", + "group": "preparation", + "image_sha256": "da926459aee0a841bbdfaf80a0eb5fbead354c56794d1f3384eeba66d0a49e00", + "implementation_sha256": "a0b1a74887e5f1cf78e867f81f246bae08e872fed320a2939986c17913418524", + "model_sha256": null, + "contract_sha256": "87c9e8864f9469719e69bfd750c418e077944a6260ffc6fd3ce12daf4a1da7d5", + "requires": [ + "source.camera" + ], + "provides": [ + "camera.frames" + ], + "optional_inputs": [], + "parameter_choices": { + "cadence": [ + 1 + ] + }, + "defaults": { + "cadence": 1 + }, + "state_policy": "stateless" + }, + { + "module_id": "ddrnet", + "label": "DDRNet-39 · GOOSE", + "group": "segmentation", + "image_sha256": "489fc7d1157fd0f1cd1d82e06a15737b7b2aaaf72b2ddb2aca2992b91a97488e", + "implementation_sha256": "9a3fceb65374ccc3dccdbe02691c2b62376ff3a3a6d16439cb9f6266e73c78b0", + "model_sha256": "b99c2838051bcd7b092fd3970aa62a77d5c0bbb809c9b9afb2ff4b0ebdaa4ee6", + "contract_sha256": "197c9d7dd0f55f79992215a57e450c5442f3d1510d74083bcf123577f85da199", + "requires": [ + "camera.frames" + ], + "provides": [ + "segmentation.mask" + ], + "optional_inputs": [], + "parameter_choices": { + "cadence": [ + 1 + ] + }, + "defaults": { + "cadence": 1 + }, + "state_policy": "stateless" + }, + { + "module_id": "eomt", + "label": "EoMT Large · Cityscapes", + "group": "segmentation", + "image_sha256": "5b770178e4a5c8fbe8f8ddab3b83a598973dbe103b669851110b11a0918ab846", + "implementation_sha256": "17ac471d5c51f70b3af6fb6046e1880c731691253c338b1626702ce4ca375d2b", + "model_sha256": "c265da9a74f58f5c3f4826d23ca4ca78beac0b106cca5842beca61580de5b782", + "contract_sha256": "09ca841400b08af0607d19d346f78ab768567256c8c58789a6ade4ede8f425a0", + "requires": [ + "camera.frames" + ], + "provides": [ + "segmentation.mask" + ], + "optional_inputs": [], + "parameter_choices": { + "cadence": [ + 1 + ] + }, + "defaults": { + "cadence": 1 + }, + "state_policy": "stateless" + }, + { + "module_id": "tgs", + "label": "TRAVEL TGS · облако и карта проходимости", + "group": "geometry", + "image_sha256": "f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3", + "implementation_sha256": "52813392aabd02efc5c2b8f7c22ed88e3ef4cc8ad3aafeba2792efe503e29fe9", + "model_sha256": null, + "contract_sha256": "9dd80c8e2504559d2156fca933de6eb27901e35305e6853aeb84707e1cb13892", + "requires": [ + "source.calibration", + "source.lidar", + "source.pose" + ], + "provides": [ + "geometry.costmap", + "geometry.ground" + ], + "optional_inputs": [], + "parameter_choices": { + "history-seconds": [ + 1 + ] + }, + "defaults": { + "history-seconds": 1 + }, + "state_policy": "causal-reset-at-source-start" + }, + { + "module_id": "rf-detr", + "label": "RF-DETR Large · рамки объектов", + "group": "detection", + "image_sha256": "2b8b44be8e9ee4060aa6997fc4c025ad7120f37ecd720a9e59b5e02ac6c90f66", + "implementation_sha256": "4eb580eb938164bf0624e94fdc3b046aacf32fb8022c93c67fa26bab7c3d19d0", + "model_sha256": "b8a40b3580edff001ec9680de68707242294ff590ab296000fae371f1083f695", + "contract_sha256": "815d0afd24355da3a462e0423dab8284165c89cebd136d7c8584a32602178b96", + "requires": [ + "camera.frames" + ], + "provides": [ + "detections.2d" + ], + "optional_inputs": [], + "parameter_choices": { + "cadence": [ + 1 + ] + }, + "defaults": { + "cadence": 1 + }, + "state_policy": "stateless" + }, + { + "module_id": "object-distance", + "label": "Дистанция до объектов · K1 LiDAR", + "group": "range", + "image_sha256": "69d68f64981b41e5bcce1e642433e3d466b88c51942a5ba3aec9180d8ed04263", + "implementation_sha256": "0e3e426e2f768bc019a3715a50fc77a88626869abd9fa919e1aef5763d0c53da", + "model_sha256": null, + "contract_sha256": "5a6e446f009420352587f83388331b368d00950ab2fb896c6350aaa9b31c2e2e", + "requires": [ + "detections.2d", + "source.calibration", + "source.lidar", + "source.pose" + ], + "provides": [ + "objects.ranged" + ], + "optional_inputs": [], + "parameter_choices": { + "cadence": [ + 1 + ] + }, + "defaults": { + "cadence": 1 + }, + "state_policy": "stateless" + } + ] + }, + "configured_definitions": [ + { + "setup_id": "lab-v1-eomt-ddrnet-portable-v1", + "definition_sha256": "269d71a24b4e63cff54e01273f9d4b35fc6cdd72bc6fadec206169ae0777e6ac", + "version": 2, + "executor": { + "contour_id": "worker-006", + "image_sha256": "5ad7d95baac63af13812cb693d492add4e806a333aba8e60edb2ea1aba754373", + "reason": null, + "reason_code": null, + "release_id": "lab-v1-installed-package-v1", + "release_sha256": "667858623962cd6d9849a8985b803f59e429916b5c56f76a6fc6c80c0c54526b", + "state": "ready" + }, + "resource_profile": { + "accelerator_id": "nvidia-rtx-4090", + "allowed_checkpoints": [], + "checkpoint_policy": "non-checkpointable", + "concurrency": 1, + "contour_id": "worker-006", + "profile_id": "worker006-single-gpu-sequential-ai-v1", + "profile_sha256": "7468138cad115210eda18e7a3350e3423d3d39ac0aae650b3266cdc2bc63fd5d", + "schema_version": "missioncore.observatory-portable-resource-profile/v2" + } + }, + { + "setup_id": "m49-tgs-portable-v2", + "definition_sha256": "f56d6321bd794ccdfb7d2e3b05d044b11f616ffb81ee29517386cc253046d4eb", + "version": 3, + "executor": { + "contour_id": "worker-006", + "image_sha256": "f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3", + "reason": null, + "reason_code": null, + "release_id": "m49-tgs-portable-executor-v1", + "release_sha256": "c5b0670d943fe0452ef4bbfbc144ab2439a1a674f9ef164798ad9f8b1ecc29fa", + "state": "ready" + }, + "resource_profile": { + "accelerator_id": "cpu-only", + "allowed_checkpoints": [], + "checkpoint_policy": "non-checkpointable", + "concurrency": 1, + "contour_id": "worker-006", + "profile_id": "worker006-cpu-single-run-portable-v2", + "profile_sha256": "49e373f1cbf314e7fab2d176db295f3d3d9ddbbcbd724bbde988ef60ad767dee", + "schema_version": "missioncore.observatory-portable-resource-profile/v2" + } + }, + { + "setup_id": "ai-segmentation-ddrnet-v1", + "definition_sha256": "04dd11b9bca4956bc253c970a9020a5fac80e9ef5981ff1fffc32b9646087fec", + "version": 1, + "executor": { + "contour_id": "worker-006", + "image_sha256": "7a1d425b4678dcade7d7d6ffd14733d639a4df29f45e1759ba4c512e930da8ab", + "reason": null, + "reason_code": null, + "release_id": "ai-modular-installed-package-v1", + "release_sha256": "97bfe743689766285b22627c4020d10df7949ef1f4546ef904dccb9ca4c6f721", + "state": "ready" + }, + "resource_profile": { + "accelerator_id": "nvidia-rtx-4090", + "allowed_checkpoints": [], + "checkpoint_policy": "non-checkpointable", + "concurrency": 1, + "contour_id": "worker-006", + "profile_id": "worker006-single-gpu-sequential-ai-v1", + "profile_sha256": "7468138cad115210eda18e7a3350e3423d3d39ac0aae650b3266cdc2bc63fd5d", + "schema_version": "missioncore.observatory-portable-resource-profile/v2" + } + }, + { + "setup_id": "ai-segmentation-eomt-v1", + "definition_sha256": "387f42bdf707b0e3e357fec1cfb5aa90a64133ebf0095f9b01d749ca2364d47c", + "version": 1, + "executor": { + "contour_id": "worker-006", + "image_sha256": "7a1d425b4678dcade7d7d6ffd14733d639a4df29f45e1759ba4c512e930da8ab", + "reason": null, + "reason_code": null, + "release_id": "ai-modular-installed-package-v1", + "release_sha256": "97bfe743689766285b22627c4020d10df7949ef1f4546ef904dccb9ca4c6f721", + "state": "ready" + }, + "resource_profile": { + "accelerator_id": "nvidia-rtx-4090", + "allowed_checkpoints": [], + "checkpoint_policy": "non-checkpointable", + "concurrency": 1, + "contour_id": "worker-006", + "profile_id": "worker006-single-gpu-sequential-ai-v1", + "profile_sha256": "7468138cad115210eda18e7a3350e3423d3d39ac0aae650b3266cdc2bc63fd5d", + "schema_version": "missioncore.observatory-portable-resource-profile/v2" + } + }, + { + "setup_id": "ai-detection-rf-detr-v1", + "definition_sha256": "598ce44f087c392ee95a024c3c45c95bdd02ad8530a3ccbac13422c2ad2f4a94", + "version": 1, + "executor": { + "contour_id": "worker-006", + "image_sha256": "7a1d425b4678dcade7d7d6ffd14733d639a4df29f45e1759ba4c512e930da8ab", + "reason": null, + "reason_code": null, + "release_id": "ai-modular-installed-package-v1", + "release_sha256": "97bfe743689766285b22627c4020d10df7949ef1f4546ef904dccb9ca4c6f721", + "state": "ready" + }, + "resource_profile": { + "accelerator_id": "nvidia-rtx-4090", + "allowed_checkpoints": [], + "checkpoint_policy": "non-checkpointable", + "concurrency": 1, + "contour_id": "worker-006", + "profile_id": "worker006-single-gpu-sequential-ai-v1", + "profile_sha256": "7468138cad115210eda18e7a3350e3423d3d39ac0aae650b3266cdc2bc63fd5d", + "schema_version": "missioncore.observatory-portable-resource-profile/v2" + } + }, + { + "setup_id": "ai-range-object-distance-v1", + "definition_sha256": "af5e637b78c670930b60cd4527b611aba4af601e6da58aa4dc8326ea6e13c5c2", + "version": 1, + "executor": { + "contour_id": "worker-006", + "image_sha256": "7a1d425b4678dcade7d7d6ffd14733d639a4df29f45e1759ba4c512e930da8ab", + "reason": null, + "reason_code": null, + "release_id": "ai-modular-installed-package-v1", + "release_sha256": "97bfe743689766285b22627c4020d10df7949ef1f4546ef904dccb9ca4c6f721", + "state": "ready" + }, + "resource_profile": { + "accelerator_id": "nvidia-rtx-4090", + "allowed_checkpoints": [], + "checkpoint_policy": "non-checkpointable", + "concurrency": 1, + "contour_id": "worker-006", + "profile_id": "worker006-single-gpu-sequential-ai-object-distance-v1", + "profile_sha256": "c244efed459915508044fed4ef0e73c810fbe750e5e379d06723f734bd4385ca", + "schema_version": "missioncore.observatory-portable-resource-profile/v2" + } + } + ], + "composition_runs": { + "schema_version": "missioncore.observatory-ai-composition-run-list/v1", + "items": [ + { + "schema_version": "missioncore.observatory-ai-composition-run/v1", + "run_id": "ai-composition-33389babab33b801e8892f7b991683487eef2deea507486e52569fe943082e4b", + "source_session_id": "20260828T130511Z_viewer_live", + "composition_sha256": "230396b858b09eea3d1d3a190c5e32d1d5e379da0058d32341026937fbb5cf24", + "module_ids": [ + "tgs", + "ddrnet", + "rf-detr", + "object-distance" + ], + "setup_ids": [ + "ai-segmentation-ddrnet-v1", + "m49-tgs-portable-v2", + "ai-range-object-distance-v1" + ], + "job_ids": [ + "observatory-run-ef3c14a64fca4d5a8674df82a5a0fca2", + "observatory-run-b230216709dc4c59bc56c98c7e329bf1", + "observatory-run-185e25280d58472ab8b4a0245a35c888" + ], + "created_at_utc": "2026-09-04T06:59:35.000Z", + "state": "ready", + "configuration_label": "RAVNOVES004TREE · DDRNet-39 · GOOSE · RF-DETR Large · TRAVEL TGS · Дистанция до объектов · K1 LiDAR", + "display_name": "DDRNet-39 · GOOSE · RF-DETR Large · TRAVEL TGS · Дистанция до объектов · K1 LiDAR", + "presentation": { + "schema_version": "missioncore.observatory-presentation-projection/v1", + "modules": [ + { + "module_id": "ddrnet", + "label": "DDRNet-39 · GOOSE" + }, + { + "module_id": "rf-detr", + "label": "RF-DETR Large" + }, + { + "module_id": "tgs", + "label": "TRAVEL TGS" + }, + { + "module_id": "object-distance", + "label": "Дистанция до объектов · K1 LiDAR" + } + ], + "configuration_label": "DDRNet-39 · GOOSE · RF-DETR Large · TRAVEL TGS · Дистанция до объектов · K1 LiDAR", + "viewer_layers": [ + { + "layer_id": "camera.source", + "pane_id": "camera", + "label": "КАМЕРА", + "control": "toggle", + "order": 10 + }, + { + "layer_id": "camera.ddrnet", + "pane_id": "camera", + "label": "DDRNET", + "control": "toggle", + "order": 20 + }, + { + "layer_id": "camera.detections", + "pane_id": "camera", + "label": "РАМКИ", + "control": "toggle", + "order": 40 + }, + { + "layer_id": "spatial.source-points", + "pane_id": "spatial", + "label": "ИСХ. ТОЧКИ", + "control": "toggle", + "order": 10 + }, + { + "layer_id": "spatial.local-slam", + "pane_id": "spatial", + "label": "ЛОК. SLAM", + "control": "toggle-with-settings", + "order": 20 + }, + { + "layer_id": "spatial.tgs", + "pane_id": "spatial", + "label": "TGS", + "control": "toggle", + "order": 30 + } + ] + }, + "jobs": [ + { + "schema_version": "missioncore.observatory-recorded-job/v1", + "job_id": "observatory-run-ef3c14a64fca4d5a8674df82a5a0fca2", + "idempotency_key": "ai-layer:fba5a33f38ba5beace38e4a4e99b4a468d2d6d760370027a9a6563b3c1279eae", + "request_sha256": "16c22588dc443c1296782a4c4034fb895f888fddc8777a6d892b9f94da99b064", + "identity_sha256": "47ddde3a49a77e9783a0ffaddff5f3219a0dc0cace1b77dbf71610575d5973b6", + "submission_receipt_sha256": "8d7267ed9f652054fc9b42afb5faa341195d3fcbaad7a3f4fcb3979f827d91da", + "source": { + "session_id": "20260828T130511Z_viewer_live", + "catalog_sha256": "2db6b8f109f5cc31bb32733ca633e03becca83d1f140a68ecc9ec9522010c24e", + "bundle_sha256": "ee8aa75ff7fbf747ad62161d6e3bc83e291253e6df219a4d1b3a07bc69c79e84", + "capability_manifest_sha256": "a4adc08ab0f867fcf7992aacaedd63328c9af222c829238c3f6e58903b95fa5e", + "adapter": { + "adapter_id": "xgrids-k1-recorded-ai-layer-v1", + "version": 1, + "adapter_sha256": "2b8e624b2b16b00c9dd75b96e4c56c5438aa6889b0b2fa7a2b2da39d6aa81c6e" + } + }, + "setup": { + "setup_id": "ai-segmentation-ddrnet-v1", + "definition_id": "ai-segmentation-ddrnet", + "definition_version": 1, + "definition_sha256": "e2f1b59e8680e0ad7e715cf61cac1bfe53b183429f933a65fd3ec22e1e198f16" + }, + "executor": { + "release_id": "ai-modular-installed-package-v1", + "release_sha256": "ecbb0edc1c4c3708329247a2210ef98dfa776bf948974e778ba6d131ad17a924", + "image_sha256": "7a1d425b4678dcade7d7d6ffd14733d639a4df29f45e1759ba4c512e930da8ab", + "model_release_ids": [ + "lab-v1-ddrnet-39-goose-fine-64-v1" + ], + "learned_models": [ + "lab-v1-ddrnet-39-goose-fine-64-v1" + ], + "model_manifest_sha256": "c9144b30d054e3d495961486a4aed70ae5f60bcadadb4e3309865ced4123739e", + "resource_profile_id": "worker006-single-gpu-sequential-ai-v1", + "resource_profile_sha256": "7468138cad115210eda18e7a3350e3423d3d39ac0aae650b3266cdc2bc63fd5d" + }, + "checkpoint_policy": { + "mode": "non-checkpointable", + "allowed_checkpoints": [], + "last_checkpoint_id": null + }, + "priority": { + "class": "recorded", + "rank": 100, + "server_owned": true + }, + "state": "succeeded", + "preemption_requested": false, + "restart_from_zero": false, + "preemption_receipt_sha256": null, + "claim_generation": 1, + "claim_lease": null, + "result": { + "result_id": "ai-layer-ddrnet-7c6a79942683933390f5ff0ecf2c6da1867d40032e91303746a567198772ce5c", + "sha256": "cbc433c51f49c63f45673f53ab5491d1cdbca04f2da7c5c9515c9f47c61cf01e" + }, + "terminal": { + "code": "result-sealed", + "message": "Recorded result was sealed by the Worker." + }, + "publication": { + "state": "published", + "attempts": 1, + "error": null, + "published_at_utc": "2026-09-04T04:26:44.704Z" + }, + "created_at_utc": "2026-09-04T03:57:16.996Z", + "updated_at_utc": "2026-09-04T04:26:44.704Z", + "authority": { + "commands_enabled": false, + "actuation_allowed": false, + "navigation_or_safety_accepted": false, + "production_accepted": false + } + }, + { + "schema_version": "missioncore.observatory-recorded-job/v1", + "job_id": "observatory-run-b230216709dc4c59bc56c98c7e329bf1", + "idempotency_key": "observatory-ui:8966e8a8-cfde-4ff1-9361-e6becd9f0a87", + "request_sha256": "b18a41134bfc18d007b2d94aed7b71dcfdb51791ae1f1f78bf8665c719a33c59", + "identity_sha256": "bbf59ed8c0087b17e14b0f5f5ea903456e17f05bd4c7608744c05671c4e1382b", + "submission_receipt_sha256": "72b4d576ec79cf9df64d8a7c1f9c4decd316c52c1f0dcd48438dc3323cc4642b", + "source": { + "session_id": "20260828T130511Z_viewer_live", + "catalog_sha256": "2db6b8f109f5cc31bb32733ca633e03becca83d1f140a68ecc9ec9522010c24e", + "bundle_sha256": "2412ee2374590a3b0bca8849a2410188325397b1651b7ae2916c48ead664c417", + "capability_manifest_sha256": "c7c23096144bbb28b62edb1a8dad1b916decfac82c781687d22380721cafba96", + "adapter": { + "adapter_id": "xgrids-k1-recorded-observatory-v2", + "version": 2, + "adapter_sha256": "4e12be6d2503e2e237eddb290b28d6a7d16cf983855b6d8e6b4e3b65d2feb0de" + } + }, + "setup": { + "setup_id": "m49-tgs-portable-v2", + "definition_id": "m49-tgs-portable", + "definition_version": 3, + "definition_sha256": "f56d6321bd794ccdfb7d2e3b05d044b11f616ffb81ee29517386cc253046d4eb" + }, + "executor": { + "release_id": "m49-tgs-portable-executor-v1", + "release_sha256": "c5b0670d943fe0452ef4bbfbc144ab2439a1a674f9ef164798ad9f8b1ecc29fa", + "image_sha256": "f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3", + "model_release_ids": [], + "learned_models": [], + "model_manifest_sha256": "489a43448f720a9b5c7993dc8279d167b77191a586f0d87b6d38b81cf728e2f1", + "resource_profile_id": "worker006-cpu-single-run-portable-v2", + "resource_profile_sha256": "49e373f1cbf314e7fab2d176db295f3d3d9ddbbcbd724bbde988ef60ad767dee" + }, + "checkpoint_policy": { + "mode": "non-checkpointable", + "allowed_checkpoints": [], + "last_checkpoint_id": null + }, + "priority": { + "class": "recorded", + "rank": 100, + "server_owned": true + }, + "state": "succeeded", + "preemption_requested": false, + "restart_from_zero": false, + "preemption_receipt_sha256": null, + "claim_generation": 1, + "claim_lease": null, + "result": { + "result_id": "m49-tgs-portable-review-a09d2b4a07d103e4f3693ba746a51be2197214768774eabfded4f109ae80dce4", + "sha256": "52e8afd6aaa38b615008463b873b94feae160946a69ce67aba12efc5f12b1589" + }, + "terminal": { + "code": "result-sealed", + "message": "Recorded result was sealed by the Worker." + }, + "publication": { + "state": "published", + "attempts": 1, + "error": null, + "published_at_utc": "2026-09-03T08:31:39.776Z" + }, + "created_at_utc": "2026-09-03T08:08:03.013Z", + "updated_at_utc": "2026-09-03T08:31:39.776Z", + "authority": { + "commands_enabled": false, + "actuation_allowed": false, + "navigation_or_safety_accepted": false, + "production_accepted": false + } + }, + { + "schema_version": "missioncore.observatory-recorded-job/v1", + "job_id": "observatory-run-185e25280d58472ab8b4a0245a35c888", + "idempotency_key": "ai-layer:502ec972ec9e6d190720d1e820e6b204066ed31c560baf571797e6aed74b154b", + "request_sha256": "bf3cd7b4dd0738f1a52341ccd4b9cc39db542e83c2c7ce1dda31a80c4932bc8d", + "identity_sha256": "568a9d42642aee9ce798c5e2f8920651d1fd9b383293345a2a7ab322685900f2", + "submission_receipt_sha256": "e568e257e941e63a3e84b95311fa15e33dcf31defacacaa55b5a617c6a8731a7", + "source": { + "session_id": "20260828T130511Z_viewer_live", + "catalog_sha256": "2db6b8f109f5cc31bb32733ca633e03becca83d1f140a68ecc9ec9522010c24e", + "bundle_sha256": "2412ee2374590a3b0bca8849a2410188325397b1651b7ae2916c48ead664c417", + "capability_manifest_sha256": "c7c23096144bbb28b62edb1a8dad1b916decfac82c781687d22380721cafba96", + "adapter": { + "adapter_id": "xgrids-k1-recorded-observatory-v2", + "version": 2, + "adapter_sha256": "4e12be6d2503e2e237eddb290b28d6a7d16cf983855b6d8e6b4e3b65d2feb0de" + } + }, + "setup": { + "setup_id": "ai-range-object-distance-v1", + "definition_id": "ai-range-object-distance", + "definition_version": 1, + "definition_sha256": "af5e637b78c670930b60cd4527b611aba4af601e6da58aa4dc8326ea6e13c5c2" + }, + "executor": { + "release_id": "ai-modular-installed-package-v1", + "release_sha256": "97bfe743689766285b22627c4020d10df7949ef1f4546ef904dccb9ca4c6f721", + "image_sha256": "7a1d425b4678dcade7d7d6ffd14733d639a4df29f45e1759ba4c512e930da8ab", + "model_release_ids": [ + "rf-detr-large-native-kb4-v1" + ], + "learned_models": [ + "rf-detr-large-native-kb4-v1" + ], + "model_manifest_sha256": "edef8446597b801f67538e9e1f056cbb55e56bf61ca4127efd97ce98e7473788", + "resource_profile_id": "worker006-single-gpu-sequential-ai-object-distance-v1", + "resource_profile_sha256": "c244efed459915508044fed4ef0e73c810fbe750e5e379d06723f734bd4385ca" + }, + "checkpoint_policy": { + "mode": "non-checkpointable", + "allowed_checkpoints": [], + "last_checkpoint_id": null + }, + "priority": { + "class": "recorded", + "rank": 100, + "server_owned": true + }, + "state": "succeeded", + "preemption_requested": false, + "restart_from_zero": false, + "preemption_receipt_sha256": null, + "claim_generation": 1, + "claim_lease": null, + "result": { + "result_id": "ai-layer-object-distance-05f3931621585c9ac32132bef8c7afa961cea317cc29def09a8312339f8421e4", + "sha256": "05e9431dd5cfb7e55b8d59644cdadccf67588974975455e376d37f880f4652f6" + }, + "terminal": { + "code": "result-sealed", + "message": "Recorded result was sealed by the Worker." + }, + "publication": { + "state": "published", + "attempts": 1, + "error": null, + "published_at_utc": "2026-09-04T07:00:02.263Z" + }, + "created_at_utc": "2026-09-04T06:29:36.181Z", + "updated_at_utc": "2026-09-04T07:00:02.263Z", + "authority": { + "commands_enabled": false, + "actuation_allowed": false, + "navigation_or_safety_accepted": false, + "production_accepted": false + } + } + ], + "result_ids": [ + "ai-layer-ddrnet-7c6a79942683933390f5ff0ecf2c6da1867d40032e91303746a567198772ce5c", + "m49-tgs-portable-review-a09d2b4a07d103e4f3693ba746a51be2197214768774eabfded4f109ae80dce4", + "ai-layer-object-distance-05f3931621585c9ac32132bef8c7afa961cea317cc29def09a8312339f8421e4" + ] + } + ] + }, + "recorded_jobs": { + "ai-segmentation-ddrnet-v1": [ + { + "job_id": "observatory-run-ef3c14a64fca4d5a8674df82a5a0fca2", + "state": "succeeded", + "publication": { + "state": "published", + "attempts": 1, + "error": null, + "published_at_utc": "2026-09-04T04:26:44.704Z" + } + }, + { + "job_id": "observatory-run-884ad2f787244abdb12373a8f6f2d2e0", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-db32fced93ad46b6a3f7d2ff7421a557", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-77f8470a8593454ab777bcacf2d47b9f", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-24de2abb929a42738e4cfef6c4e86b95", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-cc9c9c5cd18844f0ab25fb20524e5073", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-1079d7c81ea0499e86738abfc1c35f49", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + } + ], + "ai-segmentation-eomt-v1": [], + "ai-detection-rf-detr-v1": [], + "ai-range-object-distance-v1": [ + { + "job_id": "observatory-run-185e25280d58472ab8b4a0245a35c888", + "state": "succeeded", + "publication": { + "state": "published", + "attempts": 1, + "error": null, + "published_at_utc": "2026-09-04T07:00:02.263Z" + } + }, + { + "job_id": "observatory-run-cef3ba45c2024c55b6fb461e653d7187", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-5ab19401156d4d05b770ba57384387f0", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-f1a3cd0475964d62867cf17f135efbaa", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-96c0b491ae604772af19bca478837599", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-ee9d0b283b68470c91db5199a0374146", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-500a5a3b31e34061b52e1c09ff4f9604", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + } + ], + "m49-tgs-portable-v2": [ + { + "job_id": "observatory-run-b230216709dc4c59bc56c98c7e329bf1", + "state": "succeeded", + "publication": { + "state": "published", + "attempts": 1, + "error": null, + "published_at_utc": "2026-09-03T08:31:39.776Z" + } + }, + { + "job_id": "observatory-run-d9e1089a503d46988847ad9f86cbf7d9", + "state": "succeeded", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-e8645450dbe74f08b5944f35d3ee5c9f", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + }, + { + "job_id": "observatory-run-a627da1692cb4a2a9106d3e7e2870a90", + "state": "failed", + "publication": { + "state": "not-required", + "attempts": 0, + "error": null, + "published_at_utc": null + } + } + ] + }, + "desktop_documents": { + "archived_at": "2026-09-05", + "role": "historical_desktop_reports_not_current_instructions", + "files": [ + { + "filename": "_MISSING_CORE_MODULAR_AUDIT_AND_PLAN_2026-09-03.md", + "sha256": "d6c201d083fbec4b1db031379b515ff821a09ccfa0cea62443e211a9d76cb1c2", + "bytes": 53637 + }, + { + "filename": "_MISSING_CORE_OBSERVATORY_DOCKER_LABS_FINAL_STATUS_2026-09-01.md", + "sha256": "45e870700baddab8f31a2f0f0bfe1f9e99e8e73a490195c1e6a3beb5265e49ee", + "bytes": 330260 + } + ] + } +} diff --git a/docs/handoff/ai-inference-source-documents/README.md b/docs/handoff/ai-inference-source-documents/README.md new file mode 100644 index 0000000..992805b --- /dev/null +++ b/docs/handoff/ai-inference-source-documents/README.md @@ -0,0 +1,15 @@ +# Исторические исходники AI Inference + +Полные побайтные копии двух Desktop-отчётов, заархивированные 2026-09-05. +Размеры и SHA-256: [manifest.json](manifest.json). + +Текущий архитектурный срез и интерпретация старых результатов: +[AI Inference — принципы и архитектура](../../audits/2026-09-05-ai-inference-architecture.md). +Полный актуальный контекст также опубликован отдельной картой AI Inference в Ops / MISSION CORE. + +Эти исходники исторические. Содержащиеся в них планы, слова CURRENT, «следующий +шаг» и старые требования к монолитной упаковке не являются текущими инструкциями. +Их даты измерений и ограниченная область доказательства сохраняются. + +Оригиналы на Desktop автоматически не удалялись. После публикации этого архива +они могут быть удалены владельцем без потери именно этих двух документов. diff --git a/docs/handoff/ai-inference-source-documents/_MISSING_CORE_MODULAR_AUDIT_AND_PLAN_2026-09-03.md b/docs/handoff/ai-inference-source-documents/_MISSING_CORE_MODULAR_AUDIT_AND_PLAN_2026-09-03.md new file mode 100644 index 0000000..bfbf25d --- /dev/null +++ b/docs/handoff/ai-inference-source-documents/_MISSING_CORE_MODULAR_AUDIT_AND_PLAN_2026-09-03.md @@ -0,0 +1,488 @@ +# Mission Core / Missing Core — сверка модульной Обсерватории и план реализации +Дата: 3 сентября 2026. Срез runtime: 16:21–16:35 UTC. Режим: исследование и планирование. + +## 1. Вывод и границы этого прохода + +Нужная модель продукта ясна: выбранная запись K1 → «Сконфигурировать AI-слой» → выбор независимых возможностей и моделей → расчёт точной композиции → сохранённая LAB. На одной записи допустимы несколько разных композиций; одна композиция применяется к разным совместимым записям. + +Существующий код даёт хорошую основу очереди, transport, проверяемых входов, запуска Docker и публикации. Однако операторский конструктор, независимые модельные контракты и повторное использование результатов отдельных узлов ещё отсутствуют. Наличие отдельных контейнеров EoMT и DDRNet не означает их независимость: DDRNet сейчас читает входные кадры из результата EoMT. + +В этот проход: + +- Прочитан актуальный раздел 0.46 Desktop-документа, изучены связанные ADR, план, handoff и релевантная история. Указания внутри документов рассматриваются как контекст, а не как новый запрос на исполнение. +- Изучены карточки MISSION CORE через прямой Ops MCP, backend, frontend, generic Worker runtime, текущие adapters и полный экспериментальный graph. +- Выполнено реальное SSH-подключение к Worker 006, прочитаны Docker inventory и installed manifests; проверен HTTP-доступ к Core из обоих агентов. +- Исходники, установленные сервисы и Legacy не изменялись. Новые jobs, builds и inference не запускались. Контейнеры, images, volumes и caches не удалялись. +- Канон деплоя DCPLATFORM-21, Synology и rollout на борт в этот проход не применялись. +- Созданы только этот отчёт и приватные файлы сверки. + +## 2. Что именно изучено + +Рабочая копия: /Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory. +Ветка: codex/m5-1-observatory. HEAD: eff60e4. +В копии есть многочисленные ранее внесённые tracked/untracked изменения. Они сохранены и не считаются результатом этого прохода. + +Backend — Python 3.12, FastAPI, SessionStore, artifact gateway, SQLite queue, portable registries. +Frontend — React 19 / TypeScript / Vite; NODE.DC UI packages; Rerun 0.36.3. +Авторитетная запись и управление K1 принадлежат Core и K1 plugin. Worker создаёт производные результаты. + +| Область | Основные исходники | +|---|---| +| Сборка backend и подключение сервисов | src/k1link/web/app.py | +| API оператора | src/k1link/web/observatory_api.py | +| API Worker | src/k1link/web/observatory_worker_api.py | +| Реестр полных профилей | src/k1link/observatory/portable_run_definitions.py, portable_setup_projection.py | +| Admission и привязка к записи | source_admission.py, portable_queue_binding.py | +| Очередь, аренды, idempotency, publication state | recorded_jobs.py | +| Worker service и выбор executor | worker_service.py, worker_agent.py | +| Передача исходников и результатов | worker_http_transport.py, portable_artifact_transport.py | +| Общий source CAS | worker_source_cache.py | +| Установленные пакеты и запуск Docker | installed_lab_packages.py, installed_lab_package_runner.py, installed_lab_worker_service.py | +| Текущий LAB V1 | lab_v1_installed_package_steps.py, portable_lab_v1_executor.py; experiments/perception/worker/observatory_portable/ | +| Текущий M49 | m49_worker_service.py, m49_portable_executor.py, m49_portable_source.py | +| Сохранение и повторное открытие | portable_result_publisher.py, portable_result_cache.py, portable_publication_reconciler.py | +| Контракты просмотра | portable_replay.py, portable_semantic_replay.py, portable_tgs_replay.py, portable_result_view.py | +| Обсерватория frontend | apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx | +| Каталог, выбор, jobs и progress | apps/control-station/src/core/observatory/ | +| Общий LAB viewer | apps/control-station/src/components/laboratory/PortableResultReplay.tsx, CanonicalResultRerunReplay.tsx | +| Lifecycle spatial viewer | apps/control-station/src/components/RerunViewport.tsx и components/rerun/ | +| Полный экспериментальный graph | experiments/perception/worker/streaming_profile_stage1/pilot_graph.py, run_joint_pilot.py, pilot_model.py | +| Реальные алгоритмы | src/k1link/perception/{detector,geometry,motion,temporal,rolling_map,threat,rf_detr_native_object_detector}.py | +| Системная телеметрия | src/k1link/web/system_telemetry_api.py, src/k1link/compute/pipeline_telemetry.py | + +Пути без префикса в строках таблицы относятся к src/k1link/observatory/. + +Опорные документы: ADR0051, верхний текущий раздел OBSERVATORY_REALTIME_PROFILES_EXECPLAN, OBSERVATORY_MODULAR_HANDOFF_2026-09-03, каноны UI/компонентной архитектуры. Канонические Window, FieldFrame, Select и WindowFooterActions подтверждены в registry/components.json Design Guideline. + +В Ops прочитаны, в частности: + +- №73 «Обсерватория — модульные профили: решение и сверка Worker» — прямой контекст нового решения; карточка в Backlog. +- №71 «Milestone 5 · OSS-конструктор Mission Core» — общий M5 и границы Observatory. +- №50 «Фундаментальная архитектура Mission Core». +- №9 «Mission Core AI Server Worker — RTX 4090». +- №47 «[Mission Core] Worker telemetry: agent → MQTT → Timescale». +- №62/63 — отдельные TGS и integrated reference-graph испытания. +- №64/66 — sealed playback и канон интеграции Rerun. +Также просмотрены связанные карточки Worker, исходной архитектуры, LiDAR и perception. Исторические показатели этих карточек не выдаются за приёмку новых модулей. Чтение комментариев №73 завершилось транспортной ошибкой Ops MCP; содержимое самой карточки получено. Записей в Ops в этом проходе не было. + +## 3. Фактический runtime + +### Core + +- http://127.0.0.1:8000/api/health: operational=true. +- PID 2421 слушает 127.0.0.1:8000; listener на 8765 не найден. +- Recording cache: 20 entries, 653 266 743 bytes. +- Artifact cache: 9 pinned objects, 721 626 746 bytes. +- Background reconciler работает; на последнем срезе consecutive_failures=0. +- В очереди 13 jobs: 11 failed, 2 succeeded, активных jobs и live leases нет. +- Из двух succeeded одна имеет publication_state=published, другая — историческое not-required. Это не две заново принятые модульные LAB. + +Текущая опубликованная portable LAB: +job observatory-run-b230216709dc4c59bc56c98c7e329bf1; +result m49-tgs-portable-review-a09d2b4a07d103e4f3693ba746a51be2197214768774eabfded4f109ae80dce4. + +Каталог API подтверждает open-existing для M49 × RAVNOVES004TREE без разрешения повторного вычисления. Последняя LAB V1 job observatory-run-67a6bf3e4d644e4a8ee3c03b915f8f01 остаётся failed, результата нет. + +### Worker 006 + +SSH alias mission-gpu разрешён существующей конфигурацией в desktop-opj8j04.tail8d32ac.ts.net; hostname действительно DESKTOP-OPJ8J04. + +| Объект | Текущий факт | +|---|---| +| GPU | RTX 4090; driver 610.47; 24 564 MiB | +| Моментальный GPU snapshot | 1 778 MiB занято, utilization 14%; это общий счётчик устройства, не замер нового LAB | +| Контейнеры | 11 всего: 7 running, 4 stopped | +| Images / named volumes | 80 / 9 | +| Generic Observatory agent | be85dc40147a; image bfdc94ae5190…; running, restart count 0 | +| M49 Observatory agent | d58b3872d2ab; image e545a47a7ea2…; running, restart count 0 | +| Rollback-пара | a01b0fc675a0 и c51bd8d95a85; stopped | +| Frigate / Ollama | stopped, restart=no | +| Прежние Gaussian | gateway/pipeline unhealthy; terrain executor healthy | +| Прежний perception worker | running на срезе, RestartCount=450 | +| Прежний Triton | healthy | + +Повторно проверено наличие image полного прототипа: +sha256:986dbe7126992359c69da0ddda674925a5efe8e3429a6d5f60765f9c9ad34a4e +(tag ndc-k1-perception-ddrnet39-rfdetr-tgs:stage1-joint-20260901). + +Сверены SHA-256 пяти файлов внутри работающего generic agent с checkout: worker_agent.py, worker_http_transport.py, worker_service.py, worker_source_cache.py, installed_lab_package_runner.py. Все пять совпали. Поэтому замечания об этих участках относятся и к проверенному установленному агенту. + +### Текущие вычислительные пути + +LAB V1 package: +1bc84be07634ff69ac7459a2c39dc8fc9bcee33f72985dfa2c6088bb78976d8e. + +| Шаг | Image SHA-256, начало | GPU | Лимит RAM контейнера | +|---|---|---:|---:| +| prepare | 5ad7d95baac6… | 0 | 4 GiB | +| eomt | adba3dc8c97b… | 1 | 24 GiB | +| ddrnet | e6c986100613… | 1 | 16 GiB | +| assemble | 5ad7d95baac6… | 0 | 8 GiB | + +Это фиксированная последовательность prepare → EoMT → DDRNet → assemble. Лимиты RAM не являются квотами VRAM. + +M49 выполняет подготовку и CPU TRAVEL TGS через установленный бинарник внутри специализированного агента. Это ещё не самостоятельный модуль общего composer runtime. + +Согласно handoff, сохранённый M49 обработал 6 830 camera anchors, 6 811 LiDAR bindings, 19 UNOBSERVED за 1 416.763 s. Покрытый интервал 39.215–757.160 s внутри записи длительностью 808.779 s. Эти числа в этом проходе не пересчитывались; свежо подтверждены queue/result binding и доступность сохранённого результата. + +### Отдельное расхождение: hardware telemetry сейчас не работает + +Свежая проверка /api/v1/system/worker-telemetry: +source=agent-mqtt, reachable=false, error_code=telemetry-agent-unavailable. + +Дополнительные read-only проверки: + +- 127.0.0.1:18030/health: Connection refused. +- Docker API Mac по текущему socket недоступен. +- Windows service telegraf / «NDC Mission Core Telemetry Agent»: Stopped. + +Вычислительные Observatory agents при этом видят Core. Нельзя объединять эти два состояния в «Worker недоступен» или «вся телеметрия работает». Причина остановки не устанавливалась. Для будущих ресурсных замеров нужно отдельно вернуть телеметрию либо явно определить ограниченный measurement path; автоматического запуска служб в исследовании не было. + +## 4. Как сейчас идут задания и данные + +~~~mermaid +flowchart LR + UI["Обсерватория · React"] --> API["Core API · 8000"] + API --> Q["SQLite queue · exact identity"] + W["Worker agent"] -->|"pull claim v3 / heartbeat / progress"| API + Q -->|"sealed job"| W + A["Core source / artifact API"] -->|"verified source bytes"| CAS["Worker source CAS"] + CAS --> P["Подготовка записи"] + P --> C["Установленный executor / fixed-stack"] + C --> R["Запечатанный результат"] + R -->|"manifest + members"| O["Core publication / outbox"] + O --> S["Saved LAB / artifacts"] + S --> V["Общий viewer на Core"] +~~~ + +Фактический путь HTTP из каждого агента: +127.0.0.1:18080 внутри контейнера → фиксированный TCP bridge → host.docker.internal:18080 → существующий reverse SSH tunnel → Core 127.0.0.1:8000. + +Mac-owned tunnel описан в worker_tunnel_launchd.py: +-R 127.0.0.1:18080:127.0.0.1:8000 через mission-gpu. +Оба текущих агента используют BASE_URL=http://127.0.0.1:18080 и общий /source-cache. + +Это текущий лабораторный transport. Экспериментальные gRPC/binary streaming adapters полного graph существуют отдельно; они не заменяют установленную recorded queue. + +Основные свойства, которые нужно сохранить: + +1. Frontend передаёт идентификаторы данных, а не shell/Docker команды. +2. Core проверяет запись, source snapshot и доступную версию executor. +3. Queue атомарно исключает дубликаты и выдаёт одну активную аренду для recorded compute; сохраняет fencing/generation и границу live K1. +4. Worker проверяет exact identities и claim, получает bounded source streams. +5. Generic launcher разрешает только установленные images/assets/argv, идёт по dependency order, запускает шаги последовательно и удаляет принадлежащие запуску временные контейнеры. +6. Результат проверяется и публикуется на Core. Core outbox умеет повторять публикацию уже принятого пакета без inference. +7. Saved viewer читает запись и сохранённые артефакты с Core. + +Телеметрия оборудования — отдельный путь: +Windows Telegraf → MQTT → normalizer → Timescale → Core System API. +Job progress передаётся собственным Observatory HTTP-протоколом и не должен зависеть от доступности MQTT. + +## 5. Существенные разрывы между текущим кодом и composer + +### 5.1 DDRNet не независим от EoMT + +run_portable_lab_v1_ddrnet_component.py:139 вызывает _validate_eomt_input. +lab_v1_installed_package_steps.py:202 формирует для DDRNet eomt_result_root и source-frames из EoMT step. Installed manifest объявляет depends_on=[eomt,prepare]. + +Нужен самостоятельный output подготовки камеры: decoded-frame index, verified frames/chunks, source timestamps, valid-FOV/preprocessing metadata и decode-repair accounting. DDRNet и EoMT должны потреблять его независимо. Нельзя снять dependency только в JSON. + +### 5.2 Package registry уже поддерживает DAG, но только фиксированный пакет + +installed_lab_packages.py:192 связывает package с одним definition_sha256 и runtime_candidate_sha256. +worker_service.py:380 строит ready registry по этим точным парам. +worker_agent.py:428 выбирает только заранее установленную executor identity. + +Следовательно, простое добавление React Select не создаёт динамические композиции. Нужны server-owned composition registry и проверка плана на Worker по локальному реестру модулей. Новая комбинация не должна требовать image build, ручного installer или нового agent. + +### 5.3 Нет общего результата произвольного набора слоёв + +PortableResultReplay.tsx:18 распознаёт конкретные M49 и EoMT+DDRNet schemas. +portable_semantic_replay.py:67 ожидает одновременно city_masks и vegetation_masks, обе component identities и их artifacts. +lab_v1_installed_package_steps.py:158 собирает именно два component result. + +Нужен versioned result с inventory фактически вычисленных capabilities, общим source clock, coordinate frame, taxonomy и artifact references. Пример: detector-only публикует boxes/classes/scores; segmentation-only — masks/taxonomy; range появляется только при наличии соответствующего вычисления. + +### 5.4 Source admission шире потребностей отдельных алгоритмов + +Нынешние два профиля требуют camera + point-cloud + trajectory, точную camera/calibration identity и одну media epoch. RecordedSourceRequirements в portable_run_definitions.py требует video даже в общем типе. + +Для частичных композиций требования должны выводиться из выбранного графа. Segmentation и detector не должны автоматически требовать LiDAR. Для LiDAR-only режима нужно отдельно определить timestamp anchor и поддерживаемую аттестацию источника; нельзя просто убрать video из проверки текущего camera-anchored M49. + +| Запись, API-срез | Текущее состояние | +|---|---| +| RAVNOVES004TREE, 808.779 s | video + cloud + trajectory; оба старых профиля source-compatible, M49 уже сохранён | +| RAVNOVES00, 535.718 s | video + cloud + trajectory; оба старых профиля source-compatible | +| RAVNOVES01, 517.468 s | cloud + trajectory; нет video; оба профиля сейчас блокируются уже по capture-attestation-missing | + +RAVNOVES01 — отрицательный тест текущего admission, а не уже допущенный LiDAR-only источник. Новый режим требует отдельной проверки фактической аттестации, временных и пространственных данных. + +### 5.5 Полный прототип нельзя переносить как готовый универсальный модуль + +pilot_graph.py использует настоящие detector/geometry/motion/TGS алгоритмы, но также: + +- жёстко заданные RAVNOVES00/session IDs; +- camera 800×600, конкретную KB4 calibration и valid-FOV; +- DDRNet crop/resize 600→512 и конкретный GOOSE mapping; +- связывает TGS rasterization, material projection, препятствия и policy в одном costmap method; +- удерживает state surface/association/temporal/rolling/history. + +Нужны adapters из общего SourceEnvelope, явные image transforms и taxonomy maps. EoMT нельзя подставить вместо DDRNet в этот method без mapping/geometry contract. + +### 5.6 Source CAS и финальный result cache уже есть; per-node cache отсутствует + +worker_source_cache.py повторно использует точные исходные bytes. +portable_result_cache.py проверяет уже опубликованный полный LAB. + +Промежуточные steps сейчас принадлежат попытке конкретной job. Нет независимой идентичности node-result, reusable across compositions. На cold path сначала завершается materialize всего входа, затем запускается runner. Бounded передача файлов уже есть, но это ещё не progressive compute. + +### 5.7 Cancellation/lease loss нужно довести до самого executor + +worker_agent.py:524 запускает adapter.execute синхронно и проверяет heartbeat.failed после возврата. +installed_lab_package_runner.py:326 ждёт Docker not-running; отдельного cancellation token между heartbeat и launcher нет. + +Cleanup после выхода/ошибки существует. Однако быстрое освобождение ресурсов при потере аренды или operator cancel этим не доказано. Новому runtime нужны общий cancellation context, прекращение выдачи новых chunks, остановка точных child containers/processes, bounded join и подтверждение освобождения перед следующей GPU-job. Это вывод из проверенного кода, не проведённый здесь аварийный эксперимент. + +### 5.8 Packaging и установленная resource policy ещё расходятся с целью + +EoMT использует host-mounted Python/environment/transformers/model cache/runner/FFmpeg. DDRNet использует mounted checkpoint/mapping/runner и старый vegetation adapter. Это явные текущие зависимости, но ещё не переносимый модуль без developer layout. + +В checkout EoMT DISK_FLOOR_BYTES=250 GiB. По последнему handoff установленный step image содержит прежние 350 GiB; точный installed image в этом проходе совпал с тем handoff. Внутренний файл stopped compute image заново не извлекался. Изменение policy требует новой immutable версии, а не редактирования прежнего digest. + +### 5.9 Системная видимость Docker сейчас задана старым списком + +system_telemetry_api.py:34 и :1163 строит runtime cards по CONTAINER_GROUPS: Triton, perception, Frigate, Ollama. Само появление новых module containers не даст им полноценного представления в этой проекции. + +Нужны versioned module/job events и связь по labels: module version, composition, job, attempt, node. Существующий transport телеметрии можно переиспользовать; дополнительный telemetry-agent на каждую модель не нужен. + +## 6. Предлагаемое разбиение + +Это проектирование будущих контрактов. Приведённые ndc-имена не являются уже собранными releases. + +| Узел / группа | Кандидат | Вход → результат | Независимость | +|---|---|---|---| +| Внутренняя подготовка, без выбора модели | Source adapter / decoder | raw source → verified bounded camera/LiDAR/pose chunks и индексы | Подготавливает только нужные графу каналы; не запускает ML | +| Сегментация | ndc-k1-segmentation-ddrnet39 | Camera + preprocessing → mask + GOOSE taxonomy + transforms | Без EoMT, detector и LiDAR | +| Сегментация, альтернатива | ndc-k1-segmentation-eomt-cityscapes | Camera + preprocessing → mask + versioned taxonomy | Без DDRNet; output adapter фиксируется отдельно от raw labels модели | +| Детекция | ndc-k1-detection-rfdetr | Camera/FOV → bbox, class, score | Без segmentation; текущий RF-DETR-L native KB4 wrapper сохраняется как точная версия | +| LiDAR / TGS / geometry costmap | ndc-k1-lidar-tgs | Cloud + необходимая pose/history → ground/occupied/rejected/unobserved | Без semantic detector и segmenter; camera нужен лишь если выбран camera-anchored режим | +| Объектная геометрия / расстояния | ndc-k1-object-geometry | Objects + cloud + pose/calibration/time binding → metric association/range | Не требует segmentation; geometry-only output не выдаётся за semantic detection | +| Temporal / motion | ndc-k1-object-motion | Geometry observations + bounded history → tracks/motion/retention | Явный state/history/reset contract | +| Semantic fusion / policy-shadow | ndc-k1-policy-shadow | TGS, material projection и объявленные obstacle/temporal outputs → наблюдаемые policy outputs | Зависимости задаются конкретным policy provider | + +Тесно связанные temporal/motion/rolling функции допустимо держать в одном модуле. Аналогично TGS и его геометрическую rasterization/costmap. Логическая dependency не требует отдельного процесса для каждого математического шага. + +Разделять TGS и semantic fusion нужно хотя бы в контракте: TGS-only не должен скрыто запускать segmentation. В полном pilot graph они сейчас соединены кодом. + +Текущий detector использует RF-DETR-L с COCO-derived классами и ограниченным risk-class subset: человек, ряд транспорта и животных. Фраза «детекция всех объектов» не соответствует этому контракту. Дальность named object требует association; сегментация сама по себе расстояние не создаёт. + +## 7. Контракты и идентичность + +Предлагаемые новые исполнимые сущности: + +- ModuleSpec: stable ID/version, image digest, code/weights/assets digests, capabilities, input/output schema, taxonomy, preprocessing, resource profile, state model. +- CompositionSpec: canonical nodes + module versions + parameters + typed edges + requested outputs + cadence/precision/history/reset rules. +- CompositionRun: composition digest + source snapshot + выбранный временной диапазон + execution attempt/ownership + node outcomes + publication. +- NodeResultManifest: exact input/output identities, actual coverage/gaps, computed/reused status, artifacts и timings. +- CapabilityResult: единый сохранённый LAB с перечислением доступных слоёв, renderer-neutral artifact refs и provenance. + +Ключевые правила: + +1. CompositionSpec не содержит конкретную запись, labels UI, Docker host paths, argv или credentials. Он переиспользуем. +2. Core выдаёт data-only manifest. Worker разрешает module IDs только через собственные установленные ModuleSpecs. +3. Worker подтверждает capability snapshot и exact module versions. Текущего списка готовых полных executor identities недостаточно для произвольного composer. Рекомендуется versioned extension capability/claim contract с сохранением чтения v3 для старых jobs; конкретная версия фиксируется в этапе 1. +4. Composition digest не зависит от порядка кликов; зависит от значимых modules/parameters/edges/outputs/time rules. +5. Node cache key включает module identity, relevant source/preparation inputs, hashes upstream outputs, effective parameters, calibration/transforms/taxonomy, cadence/precision и state/history. +6. В node cache key нельзя включать job ID или digest всей композиции: это уничтожит reuse при изменении независимой ветки. Job/attempt/composition сохраняются в provenance отдельно. +7. Для stateful узлов совпадения frame ID недостаточно: нужны initial state или checkpoint identity, input prefix/history, reset/epoch и time range. +8. Смена detector сохраняет независимую segmentation; пересчитывает association и всё, что от него зависит. Смена segmentation сохраняет detector, но меняет semantic fusion. +9. Массивы передаются локально на Worker: immutable chunks/files/mmap refs с размером, dtype, shape, digest, clock и coordinate frame. В API идут bounded metadata. Промежуточные tensors не ходят Worker→Core→Worker. +10. Final publication связывает node artifacts с новой job независимо от происхождения computed/reused. Наличие частичного node cache не делает LAB завершённой. +11. Нужны atomic cache publication, validation перед reuse, quarantine damaged entries, retention pins для активных jobs/готовых LAB/retry/rollback. +12. Одна композиция владеет Worker 006; тяжёлые GPU стадии исполняются последовательно. Процесс модели живёт на протяжении её обработки записи, а не создаётся на каждый кадр. + +## 8. Поведение интерфейса + +В существующей Обсерватории рядом с выбранной записью постоянно доступна кнопка «Сконфигурировать AI-слой». Наличие уже рассчитанных LAB или активной job не должно убирать вход в настройки. Если источника вообще нет, нужен обычный empty state. + +Модальное Window: + +- Сегментация: «Не использовать» / DDRNet / EoMT. +- Детекция: «Не использовать» / RF-DETR. +- LiDAR/TGS: допустимый provider либо отключено. +- Расстояния, motion, policy-shadow — по availability и объявленным зависимостям. +- По одному provider на группу; один module с несколькими capabilities не запускается несколько раз. +- Модели остаются в списках после расчёта. Готовность относится к целой композиции. +- Недоступные сочетания объясняются внутри формы. Зависимости нельзя молча исправлять включением другой ML-модели. +- Пустой состав без вычисляемого output не создаёт LAB. +- Оператору показываются имена моделей/возможностей; технические digests и Docker paths остаются в engineering details. + +Состояния точного source × composition: + +| Состояние | Действие | +|---|---| +| Допустим, ещё не рассчитан | Рассчитать | +| Уже принят / queued / running | Показать существующую job и реальный progress | +| Полностью опубликован и проверен | Открыть сохранённую LAB | +| Расчёт завершён, публикация требует повтора | Повторить публикацию без inference | +| Недопустим или нет installed module | Причина несовместимости; настройки остаются открываемыми | +| Расчёт failed/cancelled | Честный terminal state и допустимый повтор; partial node cache не выдаётся за готовую LAB | + +Никаких отдельных страниц/микроприложений на модель или новую LAB. Компоненты формы — отдельные bounded feature modules, чтобы не расширять бесконечно ObservatoryWorkspace.tsx/App.tsx. + +Escape сначала закрывает открытый Select, затем окно; проверяются focus restore, normal/expanded viewer, close/reopen и release ресурсов. Отображаются только реально рассчитанные capabilities; старые Legacy overlays не используются для заполнения отсутствующих слоёв. + +## 9. План реализации + +### Этап 1 — executable contracts и граница миграции + +1. Зафиксировать ModuleSpec / CompositionSpec / NodeResult / CapabilityResult и source requirements по графу. +2. Построить server-side dependency admission: один segmenter; detector-only и segmentation-only допустимы; distance без нужных входов отклоняется. +3. Спроектировать dynamic composition registration и Worker capability negotiation поверх существующей очереди. Новая комбинация не требует image build/reinstall агента. +4. Реализовать canonical identities и правила reuse/invalidation, включая stateful nodes. +5. Зафиксировать coexistence новых schemas со старым installed V1/M49 и Legacy. +6. Составить retention closure существующих images/assets/packages/results/rollback. Очистку выполнять только отдельным последующим действием по проверенной достижимости; она не нужна для завершения текущего планирования. + +Выход: контрактные fixtures и тесты, точная модель admission, migration table. Новых GPU-прогонов для этого этапа не требуется. + +### Этап 2 — modules и Worker; первым сквозным результатом DDRNet-only + +2A. Вынести подготовку камеры из EoMT, создать независимый DDRNet module и общий capability result writer. +Прогнать на настоящем источнике: source → prepare → DDRNet → sealed LAB → Core viewer. Это минимальный полезный вертикальный срез. + +2B. Добавить RF-DETR detector-only и альтернативный EoMT. Доказать, что отключённые модели не загружаются. Упаковка включает закреплённый runtime и weights либо явно поставляемые immutable assets, без зависимости от случайного checkout/conda на host. + +2C. Перенести TRAVEL TGS в общий package runtime. Отделить geometry-only от semantic fusion, подключить object association, motion и policy-shadow по реальным зависимостям полного prototype graph. Убрать hardcoded source IDs; сохранить точные calibration/FOV/taxonomy contracts. + +2D. Добавить node cache, composition progress, cancellation/lease fencing, module/job labels, cleanup и retry. Обобщить capabilities системной телеметрии; перед measurement вернуть рабочий telemetry path без изменения Legacy. + +2E. Довести progressive input: bounded chunks, early-start и accounting gaps; первичная полная материализация может быть промежуточным ограничением первого вертикального среза, но не критерием завершения всего этапа. Измерять disk I/O и memory вместе с inference. + +Новый EoMT release отдельно активирует согласованную resource policy. Images старых releases не меняются на месте. + +### Этап 3 — composer и полная продуктовая приёмка + +- Подключить grouped Window к server admission и immutable compositions. +- Перенести readiness и dedup с одного фиксированного setup dropdown на source × composition. +- Добавить generic replay по capabilities: camera/mask/boxes/range/TGS/motion. Проверить отсутствие неназначенных слоёв. +- Выполнить последовательную матрицу на RAVNOVES00 и RAVNOVES004TREE; допустимость RAVNOVES01 проверять отдельно, не обходя отсутствие attestation. +- Проверить recovery, exact cache reuse, большие каталоги, закрытие/повторное открытие и освобождение RAM/GPU viewer. +- Сохранённые записи и LAB должны открываться без работающего Worker. +- Прогресс показывает фактически выполненные/переиспользованные/ошибочные узлы, source frames и coverage. Percent без измеренного total не выдумывается. + +Этапы 2 и 3 разумно выполнять вертикальными инкрементами: сначала реальная DDRNet-only LAB и её минимальная форма, затем остальные группы через те же контракты. + +### Этап 4 — будущий CUDA-борт + +Перенос тех же логических модулей на конкретное совместимое железо, долгоживущие процессы в пределах миссии, общий benchmark memory/latency/I/O. Этот этап не является условием готовности записанных лабораторий и сейчас не исполняется. + +## 10. Приёмочные сценарии + +| Сценарий | Проверяемый результат | +|---|---| +| DDRNet-only | Нет EoMT/detector процесса; есть masks и saved review | +| EoMT-only | Нет DDRNet; собственная taxonomy и корректный source transform | +| Detector-only | Есть bbox/class/score; segmentation отсутствует | +| TGS-only | Геометрические состояния без скрытой ML; clock выбран явно | +| Distance без detector/cloud/calibration | Server admission отклоняет named-object distance | +| Geometry-only без detector | Нет выдуманных semantic labels; только заявленный geometric output | +| Два segmenter / пустой граф / cycle | Отклонение на сервере, до enqueue | +| Повтор одной композиции | Существующая job или проверенная LAB, без нового inference | +| Изменён detector | Segmentation reuse; зависимые association/motion пересчитаны | +| Изменена calibration/cadence/history | Нужные cache entries инвалидированы | +| Повреждён node cache | Не принимается как hit; нет ложной готовой LAB | +| Restart Core/Worker, потеря сети | History и ownership сохранены; нет конкурентной GPU-job | +| Cancel / lease loss внутри inference | Bounded stop, освобождение exact resources до следующего владельца | +| Upload обрывается / Core publication падает | Сохранённый sealed output используется для recovery; inference не повторяется ради публикации | +| Viewer с Worker offline | Полный сохранённый просмотр с Core | +| Close/reopen, normal/expanded/Escape | Один clock/receiver, отсутствие накопления временных ресурсов | +| Две записи × две композиции | Никакой привязки результата к чужой записи или старому overlay | +| Вычисление медленнее записи | Честный wall time и полное заявленное coverage, без ложного realtime PASS | + +Existing tests для расширения: test_observatory_installed_lab_packages.py, test_observatory_installed_lab_package_runner.py, test_observatory_installed_lab_worker_service.py, test_observatory_recorded_jobs.py, test_observatory_portable_worker_runtime.py, test_worker_source_cache*.py, test_observatory_heartbeat_recovery.py, test_observatory_portable_result_publisher.py и Observatory frontend contract tests. Новый прогон тестов не выполнялся, поскольку этот проход не менял реализацию. + +## 11. Конкретные точки следующего изменения + +Предлагаемые новые bounded backend modules: +module_contracts.py, composition_contracts.py, composition_admission.py, composition_registry.py, node_result_cache.py, capability_result.py. +Окончательные имена — implementation detail; не нужно разносить каждую dataclass по отдельному файлу. + +Изменяемые существующие seams: + +- portable_run_definitions / source_admission / portable_queue_binding: переход от fixed profile к graph-derived требованиям; +- recorded_jobs / worker_agent / worker_service / worker_http_transport: composition identity, capability negotiation и cancellation; +- installed_lab_packages / installed_lab_package_runner: compilation разрешённого graph и module execution; +- отдельные adapters в experiments/perception/worker/observatory_portable; +- portable_result_* / portable_replay: generic capabilities и exact publication/review; +- ObservatoryWorkspace + отдельный AI-layer configuration feature в core/observatory и components; +- system_telemetry_api / pipeline_telemetry: динамическая module/job correlation. + +Первое реализационное действие: согласованный executable контракт независимого source preparation и DDRNet module, затем настоящий DDRNet-only вертикальный срез. Повторный полный dual-segment LAB V1 и массовая чистка Docker не закрывают этот разрыв. + +## 12. Evidence и пределы сверки + +Приватные файлы: + /Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/.runtime/observatory-context-audit-20260903 + +Содержат allowlisted inventory, hashes installed manifests, сравнение пяти исходников агента, source catalog, portable setup projections, queue summary и health/telemetry snapshot. Credentials, auth headers и содержимое записей не извлекались. + +Основной Worker inventory SHA-256: +1a960a8ec05572dbd69409dcff1030076fc785fd91e3b2c729aad19143b7e195. + +Сверка доказывает текущее устройство и перечисленные разрывы. Она не доказывает cold-start новых modules, скорость нового graph, визуальное качество, полноту покрытия всех записей или memory-lifecycle приёмку. Эти критерии включены в план, а не отмечены выполненными. + + +## 13. Ссылки на проверенные участки кода + +- [Скрытая зависимость DDRNet от EoMT](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/worker/observatory_portable/run_portable_lab_v1_ddrnet_component.py:139) +- [Формирование связанных component inputs](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/lab_v1_installed_package_steps.py:202) +- [Package привязан к конкретной definition](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/installed_lab_packages.py:192) +- [Реестр готовых установленных executor](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/worker_service.py:380) +- [Синхронный вызов executor и heartbeat](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/worker_agent.py:524) +- [Ожидание завершения Docker step](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/installed_lab_package_runner.py:326) +- [Текущая граница общего source contract](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/portable_run_definitions.py:127) +- [Viewer выбирает фиксированные result schemas](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/apps/control-station/src/components/laboratory/PortableResultReplay.tsx:18) +- [Обязательные обе segmentation ветки](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/observatory/portable_semantic_replay.py:67) +- [Жёсткие source IDs полного прототипа](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/worker/streaming_profile_stage1/pilot_graph.py:302) +- [Текущий profile selector в Обсерватории](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx:439) +- [Статический список системной телеметрии](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/src/k1link/web/system_telemetry_api.py:34) + +## 10. Реализация после сверки — 3 сентября 2026, финальный локальный срез + +Этот раздел заменяет формулировки выше о том, что модульный runtime и интерфейс ещё не реализованы. Указания исходного status-документа использовались как контекст; выполнен запрос владельца из диалога. Legacy лабораторный контур и исторический combined LAB V1 не изменялись. Канон Synology/DCPLATFORM-21 не применялся. + +### Интерфейс + +- Удалены фиксированный selector готового LAB-профиля и кнопки «Обновить»/«Рассчитать» рядом с ним. +- На их месте постоянно доступна кнопка «Сконфигурировать AI-слой» для выбранной записи. +- Каноническое модальное окно содержит отдельные функциональные блоки, статус в header, одиночный Select и нижнюю кнопку «Рассчитать». +- DDRNet и EoMT представлены как независимые альтернативы группы «Сегментация»; ни одна из моделей не выбирает и не запускает вторую. +- После отправки durable job сразу появляется в «Лабораторных доказательствах» с записью, составом, фазой, прогрессом и оценкой оставшегося времени. После публикации результат использует существующие действия просмотра, переименования и удаления. +- По последнему уточнению владельца из модального окна удалены внешняя обводка, рамки блоков, разделители header и контурные тени полей. Группировка держится на фоне, отступах и типографике. + +### Модули и Worker 006 + +Модельно-нейтральная подготовка камеры вынесена в самостоятельный шаг. DDRNet и EoMT зависят только от `camera.frames` и не читают результаты друг друга. + +| Модуль | Docker image | Image SHA-256 | +| --- | --- | --- | +| Camera source | `ndc/mission-core-ai-module-camera-source:61d1cd0adbac` | `da926459aee0a841bbdfaf80a0eb5fbead354c56794d1f3384eeba66d0a49e00` | +| DDRNet | `ndc/mission-core-ai-module-ddrnet:61d1cd0adbac` | `489fc7d1157fd0f1cd1d82e06a15737b7b2aaaf72b2ddb2aca2992b91a97488e` | +| EoMT | `ndc/mission-core-ai-module-eomt:61d1cd0adbac` | `5b770178e4a5c8fbe8f8ddab3b83a598973dbe103b669851110b11a0918ab846` | + +Общий агент `ndc-mission-core-observatory-ai-agent` запущен на Worker 006 из image SHA-256 `b7ce60a851703375e77234d9ae37dfc6221b74c9dff8de719d2a1f2772c6b089`. Он использует release `20260903-v2`, SHA-256 `a5017e73216b566d3dc61d62df1ba7bbaf1fb348dde26e42d818a121e7a4aef5`. На финальном срезе контейнер `running`, `RestartCount=0`; Core получает его claim-запросы с HTTP 204. + +| Setup | Definition SHA-256 | Package SHA-256 | +| --- | --- | --- | +| `ai-segmentation-ddrnet-v1` | `3adeba6595e31503a21f731f4b1427b09c64705c4a506659854c7c366b2d144f` | `958aa340819b42880cb79001efed946f369272937bd166e1844ee57784c6fd78` | +| `ai-segmentation-eomt-v1` | `499105c06a50b046ef1c5cd2148254e916156528ad21a824a66b787915a7f96b` | `019205fd5f0e6253759f4e7cf7aa1daa6d132163d36d4be5f8d07cca3ad1598d` | + +Для записи `20260828T130511Z_viewer_live` оба setup прошли три независимые живые проверки: `source_compatible=true`, `executor_ready=true`, `submission_allowed=true`. Во время QA пользовательская запись не отправлялась на реальный GPU-прогон. + +### Проверка + +- Backend: 98 целевых pytest-проверок модульной композиции, setup/admission, Worker integration, adapters, release и replay — успешно. +- Frontend: 749 unit-тестов — успешно; TypeScript typecheck и production build — успешно. +- Ruff и mypy по новому backend/Worker контуру — успешно. +- Release-файлы сверены по SHA-256 между локальной копией и Worker 006. +- В браузере проверены отсутствие старых controls, независимый выбор DDRNet/EoMT, закрытие модалки и итоговый вариант без обводок. diff --git a/docs/handoff/ai-inference-source-documents/_MISSING_CORE_OBSERVATORY_DOCKER_LABS_FINAL_STATUS_2026-09-01.md b/docs/handoff/ai-inference-source-documents/_MISSING_CORE_OBSERVATORY_DOCKER_LABS_FINAL_STATUS_2026-09-01.md new file mode 100644 index 0000000..fd18ba0 --- /dev/null +++ b/docs/handoff/ai-inference-source-documents/_MISSING_CORE_OBSERVATORY_DOCKER_LABS_FINAL_STATUS_2026-09-01.md @@ -0,0 +1,3556 @@ +# Mission Core — Обсерватория: модульные Docker-профили и контекст передачи + +## 0.46. АКТУАЛЬНОЕ РЕШЕНИЕ И HANDOFF — 3 сентября 2026 года + +**Это последний файл.** К исходному имени добавлено `_`; дата в имени сохранена +для преемственности. Весь актуальный контекст находится в этом разделе0.46. +Ниже специального разделителя сохранена прежняя история до0.45 без переписывания +замеров. Её слова «актуально», CURRENT, «далее», старые этапы и ограничения +не отменяют решения0.46 и не являются командами следующему чату. + +Статус этого прохода: проверены код и установленный Worker, выполнена ограниченная +очистка, обновлены архитектура и план. **Новый модульный runtime и новый интерфейс +пока не реализованы; новые модельные образы не собирались. Лабы целиком не закрыты.** + +### A. Что именно строим + +Запись K1 с камерой, облаком и доступной калибровкой появляется в Обсерватории +без рассчитанных LAB. Оператор выбирает для неё состав AI-слоя, рассчитывает его, +смотрит настоящий прогресс и получает сохранённую LAB. Потом он открывает её +без повторного inference или создаёт другую конфигурацию для той же записи. +Тот же состав можно применять к другим совместимым записям. + +Обсерватория — лаборатория качества и вычислительных характеристик. Расчёт может +идти медленнее исходной записи. Мы не добиваемся обязательного real-time через +Wi-Fi/LTE; это не условие завершения лабораторного контура. При этом сохраняются +потоковые контракты, оптимизированная подготовка, ограниченные очереди и честные +замеры стадий. Кэшированный просмотр не выдаётся за real-time inference. + +Удачная конфигурация позднее переносится на **отдельный CUDA-совместимый компьютер +на борту**. Это **не Mac Mini**: у Mac Mini другие задачи. Точные CPU-архитектура, +GPU, драйвер и inference runtime будут проверены для выбранного железа. Само +наличие CUDA не гарантирует совместимость любого старого контейнера. + +### B. Принятое изменение: модуль ≠ профиль ≠ LAB + +| Сущность | Значение | +| --- | --- | +| Docker-модуль | Независимо упакованная модель или связанная алгоритмическая функция с версией и явным I/O. | +| Профиль / композиция | Неизменяемый состав модулей, параметров, связей, правил времени и исполнения. | +| LAB / прогон | Применение точной композиции к точному снимку записи, результат и доказательства. | + +**Отменено старое требование «каждый полный профиль — новый самостоятельный +монолитный Docker».** Теперь отдельные DDRNet, EoMT и другие модули переиспользуются +в нескольких композициях. Новая комбинация сама по себе не требует ещё одного +образа со всеми весами. Существующие рабочие releases сохраняются на время миграции. + +Граница модуля — модель или связанная функция, а не каждый математический шаг. +Например, тесно связанные LiDAR/TGS geometry/costmap могут оставаться одним +модулем. Object-distance association, motion и policy выделяются по фактическим +зависимостям и измеренному обмену, а не ради числа контейнеров. Если один модуль +даёт несколько capabilities, он не запускается по экземпляру на каждую галку. + +Экономия диска возможна за счёт переиспользования моделей и общих слоёв, но Docker +уже разделяет идентичные слои образов. Сумма логических размеров images не равна +занятому месту. Несколько процессов могут потреблять больше RAM/VRAM и добавлять +копирование; приемлемость накладных расходов доказывается общим замером, не обещанием. + +Названия новых owned images/контейнеров — в пространстве `ndc-`, с понятной +моделью/функцией и версией. Примеры целевых имён, не уже созданные экземпляры: +`ndc-k1-segmentation-ddrnet39`, `ndc-k1-segmentation-eomt-cityscapes`, +`ndc-k1-detection-rfdetr`, `ndc-k1-lidar-tgs`. +LAB показывает понятное имя всей композиции. Runtime labels связывают каждый +экземпляр с module ID, composition ID и job ID; один физический модуль может +служить нескольким LAB, поэтому имя LAB не обязано совпадать с каждым контейнером. + +### C. Настройка AI-слоя в интерфейсе + +У выбранной записи — кнопка «Настройка AI-слоя», внутри существующей Обсерватории. +Она открывает компактное окно **с группами и одиночными выпадающими списками**, +не с независимыми галками всех Docker и не новый раздел приложения. + +| Группа | Предлагаемый выбор и зависимости | +| --- | --- | +| Сегментация | DDRNet **или** EoMT; не обе сразу. «Не использовать» допустимо для корректной частичной LAB. | +| Детекция объектов | Один допустимый detector, сначала существующий RF-DETR, либо отключено. | +| LiDAR / TGS / costmap | Совместимый geometry/TGS provider; конкретное разделение уточняется по коду. | +| Расстояния до объектов | Association с облаком; требует objects, калибровку и временное сопоставление. Геометрические преграды без detector — отдельный допустимый output. | +| Движение | Совместимый motion provider с объявленными входами, либо отключено. | +| Policy | Пока только наблюдение/policy-shadow; управление моторами не подключается. | + +Это группы возможностей, не обещание шести новых процессов. Окончательное +разбиение определяется контрактами этапа1. Полный желаемый экспериментальный +состав остаётся DDRNet + detector + LiDAR/range + motion + TGS/costmap + policy-shadow. +Для статических преград достаточно coarse `static_obstacle`; `hard_surface` +допустим как начальная сельская гипотеза, не доказательство безопасной навигации. +Нужные классы людей/животных проверяются по taxonomy/весам выбранного detector. + +Server admission проверяет не только число segmenter, но зависимости, поля, +source capabilities, калибровку, системы координат, временную привязку и доступные +installed версии. UI не передаёт произвольные Docker images, argv или host paths. +Нельзя скрыто добавить вторую модель или подмешать старые overlays для отсутствующего +выхода. Частичная LAB честно показывает только вычисленные capabilities. + +Состояния: + +- Точный состав не рассчитан и допустим → доступно «Рассчитать». +- Этот состав уже выполняется → реальный progress и существующая job, без дубликата. +- Точный результат опубликован → открыть существующую LAB внизу; «Рассчитать» нет. +- Можно снова открыть настройки и выбрать другой состав. Модели из групп не + исчезают из-за использования в прежней композиции: готовность относится ко всему + составу. Старое правило пустого единственного profile-dropdown этим заменено. +- Кнопок или плашек «Расчёт завершён» нет. Ошибка не создаёт готовую LAB; + частичный node-cache не считается завершённым результатом. + +Использовать канонические `Window`, `FieldFrame`, `Select`, `WindowFooterActions`, +кнопки и icons из NODEDC_DESIGN_GUIDELINE. Skill mission-core-product-ui применён +для этой схемы: новый контрол или workspace не нужен. Escape сначала закрывает +dropdown; normal/expanded и focus проверяются при реализации. UI в этом проходе +не изменялся и визуально не принимался. + +### D. Runtime: что сохраняем, что меняем + +Сохраняем общий installed-package launcher, durable queue/claim v3, ownership, +source capabilities, exact identities, source CAS, publication outbox/recovery +и единый saved viewer. Не создаём новое приложение или агента под каждую LAB/модель. + +Добавляем versioned Module/Composition registry, граф зависимостей и per-node +result-cache. Identity связывает source snapshot, image/code/weights, параметры, +preprocessing, calibration, cadence/precision, causal history/state и graph edges. +Порядок действий в настройках не влияет на identity. Смена detector может +переиспользовать независимую segmentation, но пересчитывает зависимые результаты. +Для stateful узлов учитываются начальное состояние и история, а не только frame ID. + +Один Worker006 / RTX4090 — одна активная композиция; тяжёлые GPU-вычисления +последовательны. DDRNet и EoMT — альтернативные LAB, не совместная сегментация. +Модульность не разрешает параллельно грузить4090 несколькими модельными jobs. + +Вход готовится/передаётся общим путём; промежуточные массивы передаются **локально +на Worker**, а не возвращаются на Core для отправки следующему модулю. Сохранить +bounded streaming I/O, не закреплять полную предварительную передачу/распаковку +записи как вечное условие старта. В текущем cold path такой барьер ещё есть. + +**Просмотр и финальный кэш — с Core.** Worker хранит рабочие source/preparation/ +node caches. Не заставлять viewer зависеть от живой модели или Worker. Publication +retry повторяет передачу запечатанного результата, не весь inference. +После job/cancel освобождаются временные контейнеры, buffers и RAM/VRAM; постоянные +записи и LAB не стираются ради освобождения памяти. Source CAS уже есть; новый +per-node result-cache ещё не реализован. + +На борту модули должны быть долгоживущими в пределах миссии, не стартовать на каждый +кадр. Будущий полный joint benchmark измеряет resident memory, очередь, I/O и +end-to-end latency. Сетевые лаги не равны отказу модели; безопасность и возобновление +движения — отдельный controller-контракт, не бесконечное удержание истёкшей аренды. +При необходимости горячие модули можно позднее совместно разместить по измерениям, +не теряя логической композиции. + +### E. Фактическое состояние на момент передачи + +Рабочая копия: +`/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory`. +Ветка `codex/m5-1-observatory`, HEAD `eff60e4`; много незакоммиченных изменений +предыдущих инкрементов. Не сбрасывать, не считать их созданными этим проходом. +Runtime-data Core: +`/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE/.runtime/mission-core`. + +Core `http://127.0.0.1:8000`, `/api/health`: operational=true; последний proof +2026-09-03T15:59:16Z. Процесс PID2421, обслуживаемая сборка `app-w6onjKPq.js`; +на8765 Mission Core не слушает. В этом проходе Core не пересобирался и не запускался +второй backend. Кэш записи20 entries/653266743bytes; очищать его сейчас не нужно. + +Два текущих агента Worker работают: + +- `ndc-observatory-installed-lab-worker-agent`, container `be85dc40147a`, + image `bfdc94ae5190…`. +- `ndc-observatory-m49-worker-agent`, container `d58b3872d2ab`, image `e545a47a7ea2…`. +- Их control release находится в + `D:\NDC_MISSIONCORE\runtime\services\observatory-heartbeat-recovery-20260903-OjYeg7\release`. + Полные IDs/digests и mounts сохранены в private inventory; контрольный image + агента не равен образу вычислительного шага. + +**M4.9T5:** CPU TGS сейчас выполняется внутри специализированного агента, +не нового самостоятельного модульного runner. Успешная публикация ×004TREE: +job `observatory-run-b230216709dc4c59bc56c98c7e329bf1`, +result `m49-tgs-portable-review-a09d2b4a07d103e4f3693ba746a51be2197214768774eabfded4f109ae80dce4`. +6830 camera anchors,6811 доступных LiDAR,19 UNOBSERVED, полный цикл1416.763s. +Расписание39.215–757.160s внутри808.779s сессии. Это не полное покрытие всей записи +и не весь AI-граф рига. Сохранённый camera/source/TGS viewer реализован, подробная +визуальная и повторная open/close memory-приёмка ещё открыта. + +**LAB V1:** fixed stack prepare → EoMT → DDRNet → assemble с host-mounted assets. +Package SHA256 `1bc84be07634ff69ac7459a2c39dc8fc9bcee33f72985dfa2c6088bb78976d8e`. +Последняя job `observatory-run-67a6bf3e4d644e4a8ee3c03b915f8f01` потеряла lease +на EoMT и после проверки освобождения ресурсов reconciled→failed. DDRNet и +публикация этой job не завершены. Успех нового полного LAB V1 не доказан. +Старые dual-segment results/release сохраняются как legacy compatibility, +но в новый конфигуратор такая комбинация не допускается. + +Есть инженерный прототип полного DDRNet/RF-DETR/geometry/distance/motion/TGS/ +costmap/policy-shadow, image `986dbe712699…`, а не принятый полный продуктовый LAB. +Переиспользовать его алгоритмы. Нельзя утверждать, что нынешний M49 или V1 уже +даёт полный набор или готов к автономному управлению. + +Очередь до/после очистки неизменна:11 failed,2 succeeded,0 live leases;13 job IDs, +их states/result IDs/generations совпадают. Новые compute jobs не создавались. +Ранние749 frontend/166 backend checks относятся к предыдущему saved-review +инкременту, а не к новому модульному решению. + +### F. Что очищено, что сохранено + +На Worker было24 контейнера:7 running и17 stopped. После проверки exact IDs, +writable-layer diff, mounts и отсутствия активных LAB jobs удалены **13 остановленных +предшественников/debug-экземпляров**. Осталось11:7 running,4 stopped. + +Сохранены текущие два агента и последняя rollback-пара `a01b0fc675a0`/`c51bd8d95a85`. +Также сохранены опубликованный M49, все80 images и9 volumes, source/model assets, +полный прототип, записи, Legacy и история. Прежние Ollama/Frigate по-прежнему +остановлены, restart=no. Активные Gaussian/Triton/perception пока не удалялись: +у них есть отдельные runtime-потребители/зависимости, которые нужно закрыть явно. +Часть этих служб unhealthy/перезапускается — это отмечено, но не повод слепо их снести. + +Удалённые экземпляры не восстановить с прежними Docker IDs. Журналы и сведения +об их образах/запуске/mounts сохранены; сами images/данные остаются для пересоздания +нужной службы. Архив логов не является полным snapshot контейнерных rootfs. +Сумма удалённых writable layers1175552bytes, архив журналов2078504bytes: +это очистка устаревших экземпляров, **не освобождение десятков гигабайт**. + +**Массовая очистка образов, build caches и source/model caches не выполнена.** +Она остаётся адресной задачей этапа1: построить reachable/pinned retention set, +проверить текущие packages, подготовку, historical proof и rollback, затем удалять +только недостижимое. Нельзя делать `docker system prune`, `volume prune` или +удалять все bind/cache directories. Например, образ старого rollback-контейнера +`5ad7d95baa…` всё ещё нужен prepare/assemble действующего LAB V1. + +Private evidence: +`/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/.runtime/observatory-modular-handoff-mHGULT`. +Там inventory before/after, redacted declarations, layer diffs, private logs, +cleanup receipt и verification. Raw журналы и пути assets не отправлять в Git. +Receipt SHA256 `58af029462c7fc73472ab1aae29be89f90c1412b2d4e35bfe23e3fb37c6b1030`. + +Дисковый резерв EoMT: владелец разрешил **250GiB сверх рабочего набора** вместо350. +Source и tests изменены,7 focused tests и Ruff PASS в этом проходе. +**На Worker в установленном image ещё350GiB**; активация250 требует нового +sealed image/release. Ошибка аренды старой job и дисковый floor — разные найденные +проблемы; связь причин не доказана. Не переписывать прежние digests на месте. + +### G. Четыре этапа нового маршрута + +1. **Контракты и миграция.** Сверка и первая очистка выполнены. Далее — executable + Module/Composition schemas, capability/dependency admission, exact identity, + retention closure и оставшаяся адресная чистка. Этап целиком ещё открыт. +2. **Модули и Worker runtime.** Независимо упаковать модели/функции, расширить + общий launcher, локальный обмен и per-node reuse, активировать новую resource + policy. Доказать standalone cold start без developer checkout, последовательные + реальные прогоны разных допустимых композиций, cache/recovery/cleanup. +3. **Интерфейс и полные лаборатории.** Групповой конфигуратор, source×composition, + отсутствие точных дубликатов, сохранённый синхронный viewer на Core, полное + заявленное покрытие и gaps, recovery, каталоги, normal/expanded/Escape и реальное + освобождение памяти после закрытия. Старые LAB остаются только в Legacy. +4. **CUDA-борт позже.** Квалификация фактического железа, перенос тех же логических + модулей/композиции, долгоживущий graph и joint benchmarks. Не Mac Mini; сейчас + никаких моторов, автономного запуска и утверждения safety PASS. + +### H. Куда смотреть в следующем чате + +Отчёт также записан в Ops: проект MISSION CORE, карточка№73 +«Обсерватория — модульные профили: решение и сверка Worker», +ID `a6e5bea8-5441-44ca-957f-1c117b1decf3`. Она не закрывает реализацию модулей. + +В репозитории: + +- `docs/adr/0051-modular-observatory-profiles.md` — новое решение; ADR0050 сохраняет + recorded-first, но прежний whole-profile selector и packaging заменены. +- `docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md` — единственный текущий подробный + маршрут в его верхнем разделе; название файла историческое. +- `experiments/perception/OBSERVATORY_MODULAR_HANDOFF_2026-09-03.md` — audit/cleanup, + precise identities, validation, границы доказанного и открытые пункты. +- `src/k1link/observatory/installed_lab_packages.py`, + `installed_lab_package_runner.py` — существующие package/I/O и generic launcher. +- `src/k1link/observatory/recorded_jobs.py`, `worker_agent.py`, `worker_service.py`, + `worker_http_transport.py`, `worker_source_cache.py` — queue/lease/transport/CAS. +- `src/k1link/observatory/m49_worker_service.py`, `m49_portable_executor.py`, + `lab_v1_installed_package_steps.py` — реальные сегодняшние compute paths. +- `experiments/perception/worker/observatory_portable/` — текущие packaging/adapters. +- `src/k1link/observatory/portable_publication_reconciler.py`, `portable_replay.py`, + `portable_semantic_replay.py` — publication и сохранённый viewer contract. +- `apps/control-station/src/workspaces/observatory/ObservatoryWorkspace.tsx` и + `apps/control-station/src/core/observatory/portableLaboratorySetups.ts` — текущий + UI finite-profile selector; grouped composer пока отсутствует. + +Начать с read-only сверки `git status`, Core8000 и установленных manifests, +затем с незавершённых контрактов этапа1. Не терять queue/source/publication/viewer, +не начинать заново старый realtime-first или dual-segment full-run маршрут. +Не перезапускать старые installers с зашитыми predecessor IDs. Лишь после exact +installed check создавать новую immutable release с понятным rollback. + +Работа локальная: Mac/Core + Worker006. Synology, deploy-canon21, Little Snitch, +посторонние приложения и настройки Docker Desktop не трогаем.18GB Mac не повод +для параллельных build/test/replay; только нужные последовательные проверки. +Core8000 оставлять работающим. Не делать git reset, общий prune или удаление +публикаций/записей. Не создавать отдельные LAB-микроприложения. + +Готовность передачи: документ, ADR, план и инженерный отчёт актуализированы; +новая реализация остаётся явной работой следующего чата, а не заявленным результатом. + +--- + +## ИСТОРИЧЕСКАЯ ЧАСТЬ ДО0.45 — НЕ ТЕКУЩИЙ ПЛАН + +Следующий исходный текст сохранён целиком. Его SHA256 до добавления handoff: +`7a0e57ba24eb95c95cd86aae55e24ae933de73746ecb299ce9542f6e8d2228c9`. + +# Missing Core / Mission Core M5 — записанные лаборатории, переносимые профили и будущий борт + +> АКТУАЛЬНЫЙ ПЛАН, 2026-09-03, с сохранением решения от 2026-09-02: +> сначала полноценная Observatory на записях — +> один расчёт выбранной версии профиля, реальный прогресс, сохранение и +> повторный просмотр без inference. Затем эксперименты с Docker-конфигурациями, +> затем перенос удачного профиля на фактический бортовой компьютер. +> Remote real-time через Wi-Fi/LTE больше не является блокирующим критерием. +> Актуальны разделы 0.32–0.45 и четыре этапа раздела 17. Claim-путь Worker +> восстановлен; проверенный кэш протестирован и активирован на 8000 (2026-09-03). +> Старый VM blocker снимался отдельно; остаток памяти закрытого viewer остаётся +> открытым дефектом, но не останавливает остальные части основного плана. +> Primitive-only v2 собран на8000;740 frontend/64 backend tests PASS (0.42). +> Общий source-cache и ранняя проверка LiDAR pack установлены в оба агента +> Worker;111 backend tests и межагентная проверка PASS (0.43). Первичная +> подготовка новой записи ещё целиковая; это не закрытие всего этапа2A. +> Legacy LAB исключены только из Обсерватории, архив сохранён; постраничный +> каталог активен на8000.747 frontend/41 backend tests и browser catalog PASS (0.44). +> Новый проход0.45: saved EoMT/DDRNet adapter и outbox recovery на Core, +> bounded heartbeat retry установлен в оба агента.749 frontend/166 backend tests +> PASS. Реальный LAB V1 ×004TREE не опубликован: lease failure; отдельно найден +> устаревший disk floor350GiB. Этап2 и визуальная приёмка не закрыты. +> Селектор исправлен: только совместимые нерассчитанные профили; кнопок/плашек +> «Расчёт завершён» нет. Готовые результаты — внизу. Реальные счётчики +> активированы; новый M49-run рассчитан и опубликован. Кэш/документ переживают +> перезапуск после исправления no-op reindex; визуальное видео/TGS ещё не принято. Прежние realtime-first +> требования и GO-запреты ниже — история; результаты замеров не переписаны. +> Этап 1 — реализованная и локально проверенная основа. Следующий активный +> этап 2 — полный recorded-analysis, прогресс и сквозное испытание. +> Общий camera/TGS-viewer уже работает с сохранённым результатом. Лабы целиком +> ещё не закрыты. Ближайшее: остаток2A полного анализа/входа, приёмка просмотра2B, +> затем матрица профилей/записей, recovery и большой каталог2C–2D. +> Этап4 будущий — на борт сейчас ничего не переносим. + +Следующая сводка сохранена как история старого realtime-first маршрута, +не как текущий список действий: + +> Актуализировано 2 сентября 2026 года, 22:35 МСК. Этап1 закрыт; этап2 продолжается. Инкремент18: существенный~100ms хвост локализован ниже Perception-приложения. CPU TLS A/B/A: p95 96.093/93.895/95.145ms;424/424 encrypted records и192 RPC сопоставлены,288 clocks пересчитаны. Прямой TCP без gRPC/Docker/SSH forwarding тоже даёт67.921–91.142ms пики. Mac и Worker оба на Wi-Fi; конкретный radio/AP/OS/driver механизм пока не установлен.82 local/82 Worker tests PASS. Подробности0.31. Модели/runtime не менялись и GPU не нагружался; предыдущий full-profile статус остаётся32/32 continuous, p95/p99 205.864/213.751ms FAIL,12 свежих scene. Далее — per-frame timing/очереди/10ms polling; Ethernet comparison при доступном подключении, без блокировки остального runtime. Standalone/этапы3–4 не закрыты, LAB path не переключён, actuation=false. Временные ресурсы удалены; сервисы/сеть/GPU settings не менялись, Ollama/Frigate выключены; Mac8000/Worker telemetry работают. + +## 0. Утверждённое решение перед началом реализации + +Актуальный TARGET задают разделы 0.32–0.44 и 17. Подразделы 0.1–0.31 и прежние +оценки ниже сохраняют историю решений и измерений, но не требуют достижения +сетевого realtime до реализации лабораторий. Слово `live` в исторических proof +означает реальный запуск Worker на записи, не физический поток с беспилотника. + +### 0.1 Продуктовый сценарий + +Пользователь записывает маршруты на K1 с камерой, облаком точек и pose. В Observatory он последовательно применяет разные полные профили к любому количеству совместимых записей, сравнивает результат, ошибки и способность удерживать real-time темп. В будущем mission configurator выбирает ту же проверенную immutable версию профиля вместе с зарегистрированным оборудованием и конфигурацией миссии. Во время движения этот профиль обрабатывает новые наблюдения, а не воспроизводит решения старой записи. + +Пятьсот записей и двадцать профилей — это данные и версии в общем каталоге, не пятьсот LAB-приложений и не двадцать отдельных backend/frontend реализаций. Успешный прогон знакомого маршрута — свидетельство проверки, но не автоматическое разрешение автономного движения в изменившихся условиях. + +### 0.2 Первый прототип — полный профиль, а не одна модель + +| Компонент | Что должен делать в текущем запуске | +|---|---| +| DDRNet-39 GOOSE | Семантическая сегментация и существующее coarse material mapping | +| RF-DETR native | Обнаружение и классы объектов, включая людей, кошек и собак в пределах текущего словаря | +| LiDAR + calibration + pose | Метрическая геометрия, расстояния, привязка к детекциям и препятствия без semantic имени | +| Temporal / motion | Сопровождение, оценка движения, свежесть и неизвестное состояние | +| TGS + rolling geometry | Ground/occupied/rejected/unobserved и локальная costmap | +| Fusion / policy-shadow | Согласованные слои scene, объяснимые ограничения и advisory events, без команд моторам | + +Название первого профиля: **K1 Perception — DDRNet-39 + RF-DETR + TGS**. + +Предлагаемый image: `ndc-k1-perception-ddrnet39-rfdetr-tgs:prototype-v1`. Префикс `ndc-` обязателен по правилам репозитория; реальная идентичность запуска дополнительно привязана к digest. Это имя будущего образа, не заявление о его наличии. + +Один самостоятельный образ/контейнер содержит runtime, модели, TGS, pre/postprocessing и конфигурацию. Не требуются developer checkout, отдельный старый Triton, скрытые host-cache с моделями или скачивание весов при первом запуске. Внутренние supervised процессы/изолированные среды допустимы для одной задачи восприятия; backend, broker и БД в этот образ не упаковываются. Записи, результаты и секреты остаются внешними данными. + +### 0.3 Принятые упрощения: сельская среда, static-объекты и hard_surface + +- Для столбиков и других неподвижных предметов достаточно существующего `static_obstacle` / `static.unknown`. Пользователь указал сохранённый RAV004 как пример уже имеющегося поведения. Не требуется распознавать точное имя предмета, добавлять модель столбиков, новую taxonomy или размечать датасет до первого прототипа. Этот слой нужно переиспользовать и воспроизвести из текущего потока. +- Для первого сельского прототипа **coarse `hard_surface` принят как допустимый материал**. Текущий mapper объединяет asphalt, sidewalk, bikeway и cobble; владелец осознанно принимает это объединение. Разделение дороги/тротуара/велодорожки и городской автономный транспорт не входят в scope и не являются блокерами. +- Сегментационная модель одна — DDRNet. RF-DETR решает задачу object detection; это не разрешение добавить второй segmenter. Существующие классы и алгоритмы сначала проверяются в полном runtime, без обязательного нового обучения. +- Разрешённый материал не отменяет obstacle: static-объект, занятая ячейка, отсутствие LiDAR или устаревшее evidence не превращаются в разрешение движения. Остальные материалы регулируются явным выбранным preset/config; сельский контекст сам по себе не разрешает всю растительность и грунты. +- TGS используется как реальный геометрический вход policy-shadow, а не только красивый слой viewer. Выбор объезда, маршрутный планировщик и управление физическими контроллерами пока не реализуются. + +Подтверждения reuse: [существующий vocabulary static.unknown](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/config/perception/object-semantic-vocabulary-v0.json:113), [static_obstacle в semantic taxonomy](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/config/perception/e47-semantic-slam-shadow-v1.json:44), [material mapping](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/config/perception/lab-v1-vegetation-provider-label-map-v1.json). + +### 0.4 Вычислительные и организационные границы + +- Один беспилотник → один независимый Worker → один активный полный профиль. Текущий baseline — RTX 4090; будущие 5090/H100/Apple Silicon не являются условием успеха. +- RF-DETR и DDRNet — компоненты одного профиля; оба могут быть прогреты. GPU inference первого прототипа подчинён одному сериализованному scheduler. Разные активные профили и посторонние AI-нагрузки на Worker не совмещаются. +- EoMT сохраняется отдельным резервным вариантом и отдельным образом. Его не выбрасывают, но его ускорение/переупаковка не блокирует первый полный DDRNet-профиль. EoMT и DDRNet вместе не запускаются. +- Replay 1× и будущий физический live используют один input/result contract и один вычислительный runtime. Нет полного предварительного decode, будущих наблюдений в inference и скрытого чтения старых LAB-масок/детекций/local-surface/threat результатов. +- Целевой результат — самостоятельный perception/policy-shadow прототип для последующей проверки на полигоне. Беспилотник, motors/control integration и полный mission configurator пока отсутствуют и не включаются скрыто в эту задачу. +- Никакого Synology deployment и 21-го deployment canon. Работа ограничена локальным Mission Core и Worker 006. В этапе 1 выполнены ограниченные Worker model probes и сборка диагностической общей базы; физический источник и моторы не затронуты. + +Один поддерживаемый план, ровно четыре этапа: [OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md). Он следует архитектурным границам CODEX_V5 и репозитория, отделяет CURRENT от TARGET и закрывает этапы по проверяемому результату. На 10:16 МСК этап 1 завершён как engineering baseline; этап 2 допущен к реализации, этапы 2–4 ещё не выполнены. Промежуточные частичные статусы ниже — история, не текущий gate. + +### 0.5 Промежуточный результат этапа 1 — состояние на 19:58 UTC + +Полное evidence и ограничения: [PERCEPTION_STREAM_STAGE1_2026-09-01.md](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md). + +- Добавлены transport-neutral stream/freshness/measurement contracts, [ADR 0049](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/docs/adr/0049-stream-first-perception-profiles.md) и [pinned candidate manifest](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/config/perception/k1-perception-ddrnet39-rfdetr-tgs-prototype-v1.json). Запуск нового профиля не может требовать total size, duration, полного скачивания/хеширования/декодирования записи или EOF. Старый materializer ещё не удалён: это контракт следующего runtime, не уже выполненный продуктовый cutover. +- Последовательные короткие component probes на 4090: DDRNet mean 21.52 ms с decode/pre/post; RF-DETR engine с DMA 2.30 ms на synthetic input; TGS core 1.03 ms на prepared clouds; synthetic online local-surface 63.22 ms после ограничения BLAS/OMP/MKL до одного потока вместо 198.04 ms default. Это разные границы измерения, не складываемый прогноз FPS. Полный профиль на исходном 1× потоке ещё не измерен. +- Общая диагностическая база image `sha256:664824aa25de1db178f177d67a81b01541a938b479812b9383ddbf03f6b59dbe` исполнила DDRNet Python 3.9/cu117, TensorRT 11, Python 3.12 geometry и C++ TGS отдельными последовательными probes. DDRNet masks совпали на 64 кадрах с исходным image. Веса/runner пока explicit mounts: standalone packaging, jointly resident модели и общий scheduler не доказаны. +- 78 focused tests прошли (51 новых contract + 27 существующих live-ingress/synchronizer/shadow); Ruff и mypy новых контрактов — PASS. Full backend/frontend suite, network load и physical-live не выполнялись. +- По явному решению владельца `sentinel-ollama` и `sentinel-frigate` остановлены. Docker и Compose restart=no, отдельные `manual-ollama` / `manual-frigate` profiles исключают обычный автоподъём. Данные/модели/записи сохранены; backup Compose сохранён. Эти два сервиса после замеров не восстанавливаются. Остальной временно остановленный Mission Core Worker-контур восстановлен, canonical local 8000 работает. Реального reboot не выполняли — проверены настройки автозапуска. + +**На 19:58 UTC этап 1 был частичным:** numerical budgets зафиксированы, совместный пилот ещё не выполнен. Следующий подраздел заменяет этот пункт новым фактическим результатом. Small-animal/close-large-object quality acceptance по-прежнему отсутствует; красивые viewer и component FPS его не заменяют. + +### 0.6 Совместный real-time пилот выполнен — 20:51 UTC / 23:51 МСК + +В одном временном контейнере на выделенной RTX 4090 действительно выполнен граф +**DDRNet + RF-DETR + online LiDAR/surface/расстояния + temporal/motion + TGS/costmap + policy-shadow**. +Обе модели resident, их GPU inference строго последователен. EoMT не запускался. +Камера, точки и pose подаются по исходным временам прихода 1× независимо от +скорости расчёта. Полная запись предварительно не передаётся, не хешируется и +не декодируется; прежние perception-результаты не используются. + +| Совместный пилот, 128 входных кадров | До оптимизации costmap | После | +| --- | --- | --- | +| Выдано результатов | 120 | 128 | +| Отброшено ограниченной очередью | 8 | 0 | +| Задержка source→local receiver p95 | 353.98 ms | 174.09 ms | +| Задержка p99 | 401.19 ms | 190.62 ms | +| Критерий ≤125 ms | FAIL | FAIL | + +Исправлены обнаруженная совместным запуском ошибка разделения Python 3.9/3.12 +и нехватка прошлых body poses у motion/threat: теперь хранится не более 64 +уже полученных body frames, будущие данные запрещены. Costmap lookup +векторизован без изменения алгоритмических порогов. DDRNet masks совпали +на всех 120 общих кадрах двух запусков; 86 focused tests прошли. + +Финальное окно — 12.685 s между первым и последним camera frame. Первый +результат получен через 546 ms от начала ограниченного preroll; warmup 9.36 s, +stop 4.07 s, sampled VRAM peak 1932 MiB. Очередь не превысила 2 pending frames +и 6.86 MiB observation inflight, но backlog growth 51.44 ms превышает лимит 25 ms. + +Свежая cloud/pose пара была у 75/128 кадров: для них реально рассчитаны surface, +геометрия и TGS; остальные — явно unavailable. Причины включают неравномерные +приходы/отсутствие нового инкремента и отдельный недостаток preroll-адаптера +на первом кадре. Получены 398 метрических observations, включая 275 +geometry-only static obstacles; detector видел person/car/truck. Это не +оценка accuracy и не число уникальных объектов. Cat/dog и RAV004 данным +отрезком не проверены. Устаревшие сцены не имеют разрешающих terrain actions. + +**Границы:** измерен весь вычислительный граф до collector внутри Worker, +но ещё не сеть приложение↔Worker и не viewer. Источники уже находились на Worker. +Старый backend batch materializer пока не заменён. Самостоятельный Docker пока +не поставлен: Docker Desktop не смог получить отсутствующий Triton layer +(NVCR 403), поэтому пилот выполнен на работоспособной локальной базе с +read-only code/model mounts. Этот диагностический запуск не выдаётся за +готовый portable image. + +**Статус:** совместный пилот как измерение выполнен; real-time приёмка этапа 1 +остаётся открытой. Следующая работа — DDRNet/online-surface jitter, общее +расписание при burst arrivals и layered freshness/preroll, затем повтор того +же bounded gate. Не скрываем перегрузку снижением частоты или замедлением записи. +Моторы и автономное движение не включались и не разрешены этим результатом. + +Временные контейнеры завершены; Mission Core Worker-сервисы восстановлены, +Triton healthy/ready=200, локальный Mission Core 8000=200. Ollama/Frigate +по решению владельца остаются остановленными и исключёнными из автозапуска. +Полные условия, сырые результаты и SHA-256: [отчёт этапа 1](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md). + +--- + +### 0.7 Снижение задержек — 2026-09-02 00:41 МСК + +Концепция переносимого полного Docker-профиля для разных записей сохраняется. +Текущая работа — runtime/очереди/IPC/транспорт; не управление ровером. +Перегрузка на 4090 допустима как честный лабораторный результат: тяжёлый профиль +сохраняем для дальнейшей оптимизации или другого железа, не объявляя его real-time. + +Выполнены семь коротких последовательных прогонов одного полного графа. +Layout и CUDA Graph для DDRNet не дали устойчивого сквозного выигрыша. +Добавлен экспериментальный scheduler: CPU обрабатывает предыдущий кадр, +а DDRNet → RF-DETR строго последовательно считают следующий. Разные профили +и GPU inference одновременно не запускались. Общий бюджет — два pending кадра. + +| Два повторения одного 128-frame окна | Serial | CPU/GPU overlap, shared queue | +| --- | --- | --- | +| Результаты / drops | оба 128/128, 0 drops | оба 128/128, 0 drops | +| Mean ожидание ingress | 13.65 / 25.48 ms | 7.20 / 8.31 ms | +| Source→local collector p95 | 157.82 / 232.29 ms | 143.32 / 153.44 ms | +| Source→local collector p99 | 189.69 / 256.86 ms | 198.22 / 194.25 ms | + +Это перспективное уменьшение очередей, **не гарантированное улучшение p99 и +не PASS real-time**. Неудачный промежуточный fixed-slot вариант с одним drop +сохранён отдельно. Маски, detections, метрические observations, tracks, +threats и non-timing TGS/costmap outputs совпали на всех 128 кадрах reference +и каждого shared-queue прогона. Пороги, веса, clock 1× и запрет actuation не менялись. + +Последний повтор: fresh cloud/pose у 75/128 кадров, 16 stale scenes — все без +разрешающих действий. VRAM peak 1932 MiB; GPU utilization mean 34.88%, max 83%. +Это **не «GPU загружен менее чем на 5%» и не упор в 24 GiB**. Сеть приложение↔Worker +здесь не измерена, поэтому её нельзя объявлять уже доказанным bottleneck. + +91 focused tests и Ruff — PASS. Worker-сервисы восстановлены, Triton ready=200, +local 8000=200. Frigate/Ollama остаются выключены и restart=no. Scheduler пока +экспериментальный flag; defaults и продуктовый путь не переключены. +Самостоятельный Docker и общий потоковый transport остаются следующей работой. + +Полные результаты, отрицательные прогоны и hashes: +[дополнение к отчёту этапа 1](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md). +Четырёхэтапный план сохранён; hardware performance FAIL больше не блокирует +само развитие/упаковку экспериментальных профилей. Freshness и latency gates +остаются отдельными незакрытыми статусами, не маскируются под готовность. + +### 0.8 Чистый Git checkpoint и исправление preroll — 2026-09-02 01:06 МСК + +По запросу владельца текущая ветка `codex/m5-1-observatory` зафиксирована семью +тематическими коммитами до чистой точки `ffd6be5`: equipment/capture, backend +lifecycle, Worker packaging, portable UI, streaming contracts, pilots и evidence. +Raw-записи, веса, логи и `.runtime` в Git не добавлялись; push не выполнялся. +Отдельный `05c99ef` устранил девять ошибок legacy-тестов: исторические контракты +отделены от текущих installed-package pins, проверки digest не ослаблены. + +Далее по плану исправлен source preroll binding. Старые точки первого preroll +остаются историей rolling/TGS; текущие increments получают отдельные timestamp, +age/skew и причины доступности. Повторная pose обозначается `held`, без +переноса её времени на новый camera frame. + +Сверка сохранённых метаданных 128 кадров: допустимых cloud/pose пар 76 вместо +75; изменён только первый кадр. 7,207 старых points остаются history-only, +4,787 points образуют первую текущую пару. Остальные 127 решений admission +не изменились; 52 unavailable случая не скрываются. + +Это **metadata-only проверка**, не новый GPU benchmark. Latency не объявляется +улучшенной. Новый первый geometry frame может повлиять на temporal outputs; +следующий шаг — bounded Worker pilot с повторными измерениями и проверкой +layered freshness. Готового standalone профиля и product transport cutover пока нет. + +384 focused Python tests и 62 выбранных frontend tests прошли. Нового deployment, +frontend build, остановки Worker или нагрузки моделями на Mac не выполнялось. +Полное evidence и перечень коммитов находятся в поддерживаемом четырёхэтапном плане +и дополнении к отчёту этапа 1. + +### 0.9 Bounded Worker-пилот нового preroll — 2026-09-02 01:22–01:33 МСК + +Новый binding из source commit `fd83138` проверен не metadata-аудитом, а тремя +последовательными model runs полного профиля на выделенной RTX 4090. DDRNet и +RF-DETR по-прежнему считались последовательно на GPU; geometry/distance, +temporal/motion, TGS/costmap и policy-shadow работали в том же контейнере. +EoMT, второй профиль и посторонняя GPU-нагрузка не запускались. Запись подавалась +по исходному clock 1×; источник уже находился на Worker, поэтому внешняя сеть +приложение↔Worker этим измерением не квалифицирована. + +| Run | Results / drops | Source→collector p95 | p99 | +| --- | --- | --- | --- | +| A | 127/128; seq 84 `handoff-overflow` | 127.18 ms | 143.22 ms | +| B | 127/128; seq 38 `handoff-overflow` | 125.19 ms | 138.02 ms | +| C | 127/128; seq 38 `handoff-overflow` | 120.84 ms | 135.46 ms | + +Во всех трёх случаях accounting полный: released=128, completed=127, dropped=1, +unaccounted=0. Лучший p95 отдельно не является PASS: p99 выше 125 ms, а потеря +кадра запрещает zero-drop qualification. Результат повторяемый и сохранён как +новая точка оптимизации bounded handoff, без замедления source clock. + +Исправление по существу сработало. Sequence 0 теперь `available=true` и +`surface_state=valid`: 4,787 current points, 7,207 исходных preroll points +остаются history-only, TGS реально принял 9,096 прошедших фильтрацию points. +На первом кадре сформированы 13 observations, 4 tracks и 13 threats. +DDRNet mask SHA и RF-DETR proposals совпали со старым контролем на всех 127 +общих последовательностях; camera/pose lineage также 127/127. Единственная +целевая разница point lineage/availability — sequence 0. Дальнейшие изменения +tracks/threats/TGS являются ожидаемым stateful-следствием нового первого +geometry frame, а не сменой весов или preprocessing. + +В полном admission остаются 76 current cloud/pose pairs и 52 unavailable. +Unavailable/stale не маскируются: commands_enabled и actuation_allowed равны +false во всех опубликованных сценах. Sampled VRAM = 1,931–1,937 MiB, +GPU utilization mean = 25.85–33.69%, max = 55–85%. То есть профиль не упёрся +в 24 GiB и утверждение «GPU загружен менее чем на 5%» не подтверждается. + +Evidence: `.runtime/perception-preroll-worker-20260902T0122MSK/manifest.json` +и копия на Worker +`D:/NDC_MISSIONCORE/runtime/experiments/perception-preroll-worker-20260902T0122MSK`; +manifest SHA-256 +`1b233cca8d295e89c633e642e90cf161b0a0c6d7f9411df3443e45221dd107e6`. +Временно остановленные сервисы возвращены в исходное состояние: Triton +healthy/ready=200, оба Observatory agent running, canonical Mac 8000=200, +Mac 8765 закрыт. Legacy perception Worker возобновил существовавший до пробы +HTTP 404 restart loop (running, restart count 4 на контрольном снимке); новый +пилот его не использовал, и это не объявляется healthy-восстановлением. +Ollama/Frigate остаются +exited/restart=no по решению владельца. + +**Текущий статус этапа 1:** functional full graph и исправленный preroll +подтверждены; real-time qualification не закрыта. Следующий bounded increment — +устранить `handoff-overflow`, довести layered output freshness и повторить +совокупный zero-drop + p95/p99 gate. Standalone image и внешний streaming +transport остаются последующей работой; никакого deployment или actuation не было. + +### 0.10 Direct handoff без расширения очереди — 2026-09-02 01:43–01:50 МСК + +Причина единичных drops из раздела 0.9 локализована в scheduler. Завершённый +GPU result всегда кратковременно резервировал buffered slot, даже когда +chronological CPU consumer уже ждал его в `take()`. Этот ложный третий pending +кадр выталкивал ingress. Commit `2945859` передаёт такой результат напрямую +ожидающему consumer; если consumer занят, прежняя reservation и drop-policy +сохраняются. Общий capacity=2 и byte limit=16 MiB не увеличены, source clock=1× +не замедлен, GPU inference DDRNet→RF-DETR остаётся строго последовательным. + +| Run | Results / drops | Direct / buffered handoff | p95 | p99 | +| --- | --- | --- | --- | --- | +| B | 128/128, 0 | 128 / 0 | 128.75 ms | 151.67 ms | +| C | 128/128, 0 | 127 / 1 | 122.69 ms | 157.10 ms | + +Оба запуска имеют полный accounting и peak pending=1. Zero-drop gate теперь +проходит повторяемо. Latency gate не проходит: лучший p95 не отменяет p99 +151.67–157.10 ms. Следовательно, handoff bug закрыт, а DDRNet/CPU latency tail +остаётся отдельной следующей задачей. + +Между двумя повторами совпали все 128 segmentation masks, RF-DETR proposals, +lineage/sensor binding, observations, tracks, threats, non-timing TGS, +costmap и policy outputs. В каждом — 76 fresh, 52 unavailable и 15 stale сцен; +commands/actuation везде false. Sampled VRAM 1,929–1,936 MiB, GPU utilization +mean 35.88–39.65%, max 75–76%. + +109 focused tests и Ruff прошли. Evidence: +`.runtime/perception-handoff-worker-20260902T0143MSK/manifest.json`, +Worker copy +`D:/NDC_MISSIONCORE/runtime/experiments/perception-handoff-worker-20260902T0143MSK`, +manifest SHA-256 +`d68af383c42eb3686ef199afeebd4625f27d573b77109e7e8ff8c85e811a9003`. +Первый setup launch честно исключён: pinned GOOSE runner был пропущен при +staging, preflight завершился до модели и source release; затем восстановлен +точный прежний runner. + +После проб active pilot containers=0, Triton healthy/ready=200, оба Observatory +agent running, canonical Mac 8000=200, Mac 8765 закрыт. Legacy perception Worker +возвращён в прежнюю HTTP 404 restart-loop конфигурацию. Ollama/Frigate остаются +exited/restart=no. Deployment и product cutover не выполнялись. + +**Статус этапа 1 остаётся частичным:** functional graph, preroll и zero-drop +handoff подтверждены; не закрыты p99, полноценный layered-freshness ABI, +standalone image и внешний application↔Worker streaming transport. + +### 0.11 Surface, unified Triton и реальная parity — 2026-09-02 02:47 МСК + +Продолжили этап 1, без перехода к продуктовой интеграции и без внешнего deploy. +Полный состав **DDRNet + RF-DETR + LiDAR/distance + motion + TGS/costmap + policy** +сохранён. Все 12 новых последовательных проб — 128/128, 0 drops, +исходный clock=1×, два pending кадра; GPU inference моделей не параллелился. + +- Surface cache reuse (`d9ea7c1`) убрал повторное группирование облака, + сохранив все functional outputs 128/128; surface p99 19.44/21.87 ms. +- Постоянный NVML заменил повторный запуск nvidia-smi. Проверка без telemetry + показала: наблюдатель не был главной причиной p99. +- Добавлены явные source age/sequence у segmentation/detection/geometry. + Cadence 50 ms один раз прошёл latency gate, но повтор провалился; 100 ms + тоже не закрыл gate. Default остаётся каждый кадр, без скрытой подмены + устаревшей маски свежим timestamp. +- Проверен FP32 TensorRT-кандидат DDRNet вместе с RF-DETR в одном Triton process. + Точный NumPy preprocess устранил отдельный Python-child и мегабайтный + tensor round trip. На 128 реальных K1-кадрах входные tensors совпали побитово. + +| Unified full graph | Mean | p95 | p99 | +| --- | --- | --- | --- | +| Pinned preprocess child A / B | 87.66 / 83.93 ms | 141.97 / 133.58 ms | 147.53 / 151.37 ms | +| Native NumPy C | 75.03 ms | 116.76 ms | 137.58 ms | +| C + CUDA Graphs D | 72.91 ms | 127.39 ms | 143.12 ms | +| D + busy-wait E | 73.42 ms | 118.41 ms | 138.19 ms | + +**Критически важно: TensorRT не принят как замена reference.** Всего 4,009 +пикселей из 33,554,432 отличаются от PyTorch (~0.01195%), но на кадре 115 +это изменило одну ячейку costmap `grass → hard_surface`, policy +`NO_GO → ALLOW_candidate`. Обе сцены fresh; это не timing-эффект. +Ground truth для этой ячейки не установлен. Поэтому default остаётся +PyTorch, TensorRT — только `experimental-unqualified`. NumPy preprocess +не добавляет различий; detector/расстояния/tracks/threats/геометрия/TGS +совпали с reference на всех 128 кадрах. Моторы/commands везде выключены. + +Диагностика уточнила узкое место: DDRNet server infer interval в среднем +23.61 ms, HTTP wall 28.30 ms. Но тот же engine на точном первом K1-кадре +при 64 непрерывных повторах считает GPU mean 2.67 ms, p99 3.44 ms +(без DMA и source pacing). Это **не FPS всего профиля**, а основание +проверять GPU clocks и GPU/host timeline на паузах потока. Ни сеть, +ни WDDM, ни переключение CUDA-контекстов пока не доказаны как единственная +причина. VRAM unified runs ~1,860 MiB (≈1.82 GiB); в 24 GiB не упираемся. + +119 focused tests и Ruff прошли. Все сырые прогоны, включая отрицательные, +hashes и parity сохранены в +`.runtime/perception-unified-triton-worker-20260902T0227MSK/manifest.json` +и на Worker; manifest SHA-256 +`ed81475e71b7d02af03dbc65ef628065baaec80bf4877b83e80cc6b3d682a330`. +Подробности: [отчёт этапа 1](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md). + +**Следующий шаг:** отдельно закрыть TensorRT mask/material parity и +source-paced GPU/server latency, затем довести общий streaming runtime и +layered-freshness ABI. Стабильный latency gate, внешний transport и +standalone image ещё открыты. Никакой переход к автономии не выполнен. +Triton healthy, оба Observatory agent running, Mac 8000=200/8765 закрыт, +pilot containers=0. Legacy perception Worker возвращён в прежнюю HTTP404 +restart-loop конфигурацию; Ollama/Frigate остаются exited/restart=no. + +### 0.12 Причина latency tail и fail-closed costmap — 2026-09-02 09:11–09:40 МСК + +Выполнен следующий шаг этапа 1, не новый LAB и не deployment. Session: +`perception-parity-pacing-worker-20260902T0911MSK`; код `c6c42c2`. + +Численная диагностика frame 115 показала: pinned PyTorch разрешал cuDNN TF32, +TensorRT plan собран `--noTF32`. Отключение TF32 уменьшает mismatch этого +кадра с 42 пикселей до одного, но не даёт полную parity. На critical mask pixel +raw logits предпочитают grass в обоих backend, однако TensorRT sigmoid FP32 +округляет scores grass/hard_surface до ничьей и first-index argmax выбирает +hard_surface. Postprocess не менялся: это часть pinned поведения. + +Главная policy-ошибка была ниже: в cell 1900 есть два ground votes. Reference — +grass 2; TensorRT — grass 1 + hard_surface 1. Прежний `votes.argmax` выбирал +hard_surface из-за порядка IDs и давал `ALLOW_candidate`. Теперь tied maximum +и zero votes → `unknown`; unknown → `NO_GO`. Пороги/веса/stride/freshness не +ослаблены. В двух полных повторах critical cell стабильно NO_GO. 210 cell×frame +изменений на 41 кадре направлены только в unknown, при одинаковой freshness +нет policy relaxation. TensorRT masks не объявлены эквивалентными PyTorch: +material parity остаётся 127/128 кадров, backend status — experimental. + +Read-only telemetry полного графа показала SM 2610→450–780 MHz, VRAM +10251→405/810 MHz, P2→P5/P8; `cgroup throttled_usec` не рос. По явному разрешению +владельца выполнен короткий A/B с временными штатными locks SM 2610 и memory +10501 MHz (фактически CUDA memory 10251), без разгона и изменения 450 W. +После каждого теста `-rmc/-rgc` выполнялись в `finally`. + +| Полный run, 128 кадров 1× | Mean / p95 / p99, ms | Результат | +| --- | --- | --- | +| TensorRT auto, два контроля | 73.66 / 123.14 / 138.16; после reset 70.13 / 116.71 / 144.88 | FAIL | +| TensorRT fixed clocks C/D | 44.06 / 64.08 / 70.46; 44.37 / 63.97 / 67.77 | PASS ×2 | +| Pinned PyTorch fixed clocks E | 51.08 / 71.80 / 77.02 | PASS | + +В каждом: DDRNet + RF-DETR + online LiDAR geometry/distance/static + motion + +TGS/costmap/policy, строго последовательный GPU, 128/128, zero drop/unaccounted, +две pending позиции и 16 MiB. C/D одинаковы по functional outputs 128/128. +PyTorch E сохранил pinned model outputs. GPU peak: 1863 MiB TensorRT, 2359 MiB +PyTorch; container peak C ~1380 MiB при лимите 8192 MiB; CPU quota не троттлила. +Следовательно, расширение Docker ресурсов сейчас не требуется. + +Это доказывает короткий latency PASS полного Worker-local графа при указанном +operating envelope. Не доказаны: постоянная/управляемая host policy, длинная и +другая запись, application↔Worker network, standalone image, физический live и +качество на полигоне. 52/128 cloud/pose pairs unavailable, 9–10 stale outputs +в успешных runs остаются fail-closed. Команды/actuation=false. + +Evidence manifest с точными командами, hashes и 110 artifacts: +`.runtime/perception-parity-pacing-worker-20260902T0911MSK/manifest.json`, +SHA-256 `eac303c218ab391ed5dc2cd8d94be6f1eeecec2effc123da7585135a8b63f2dd`. +Копия manifest/analysis/code archive на Worker. 122 focused tests, Ruff и +diff-check PASS. Clock reset подтверждён: P8, 210/405 MHz, 0%, 450 W. +Четыре Mission Core сервиса восстановлены, Triton ready=200; их старые failure +loops не выдаются за исправленные. Ollama/Frigate exited/restart=no. Mac +8000=200, 8765 закрыт. Raw/weights не в Git, push не выполнялся. + +**Следующий шаг этапа 1:** закрепить Worker operating envelope в preflight / +qualification manifest и layered-freshness output ABI. Затем продолжить общий +streaming runtime и application↔Worker transport. Постоянно фиксировать clocks +из контейнера без owner-scoped lifecycle/rollback нельзя. Stage 2–4 не закрыты. + +### 0.13 Общая свежесть результата и GO на этап 2 — 2026-09-02 10:16 МСК + +Commit `097e450`. Пилот использует общий контракт +`missioncore.perception-scene-freshness/v1`, а не три ad-hoc freshness поля. +Учитываются segmentation, objects, geometry, motion, costmap, policy; для каждого +сохранены epoch, source identity/time, payload hash и oldest required input. +Derived слой не может объявить старые входы свежими своим новым timestamp. +JSON int64 передаётся строками без потери точности. Приёмник проверяет реальные +payload hashes, identity и возраст; позднее использование требует новой age-check. +Unavailable не содержит придуманного payload/расстояния; пустая детекция валидна. +Полный StreamStart/lease fencing не подменяется одним epoch — это задача этапа 2. + +TGS теперь сохраняет last-seen разрешающих ячеек. История occupied/unknown +сохраняется для запретов, но не освежает разрешение. Пока guard консервативный: +одна истёкшая разрешающая ячейка запрещает **всю** advisory policy. Per-cell +expiration и оптимизация этой избыточной блокировки входят в следующий runtime, +без увеличения исходного TTL 250 ms и без моторных команд. + +Два sequential source-paced PyTorch auto-clock runs, исходный поток 1×: + +| Run | Results / drops | p95 | p99 | Fresh полных scenes при receipt | +| --- | --- | --- | --- | --- | +| B, промежуточный JSON | 128/128, 0 | 142.07 ms | 181.77 ms | 23 | +| C, финальный decimal-int64 ABI | 128/128, 0 | 122.11 ms | 141.40 ms | 27 | + +Это не controlled A/B формата JSON; скорость B/C нельзя приписать этому +изменению. Оба не проходят совместный 125-ms gate. В финальном C при publisher +guard было 32 fresh scenes; sequence 30/39/70/93/115 истекли до receipt, +consumer снял допуск. 52 camera/cloud/pose пары unavailable по источнику; +ещё 49 costmap/policy устарели. Старые «76 fresh» означали наличие sensor pairs, +не свежесть всех слоёв. Ни одного разрешающего stale/unavailable receipt нет. + +На всех 128 кадрах обоих runs совпали с прежним pinned PyTorch-reference: +маски, proposals/observations, tracks/threats, distance estimators, sensor binding, +TGS states и material arrays. Thresholds, weights и precision не изменены. +В C весь freshness + JSON + приём занимает mean 2.176 / p95 3.267 ms; +это не отдельный A/B overhead. VRAM peak 2365 MiB; cgroup memory peak +3370.79 MiB, inflight 5.20 MB, stop 4.066 s. Docker 8 CPU / 8 GiB оставлен. + +В candidate manifest закреплён measured Worker envelope: 4090 / driver 610.47, +8 CPU / 8 GiB, SM ≥2610 / memory ≥10251 MHz. Чистый read-only evaluator +проверяет snapshot age/clock domain, hardware/driver/resources, image/config, +authoritative lease, отсутствие competing clients и warmup. Unknown — не PASS, +readiness — не qualification. Controller/continuous monitoring ещё не подключены. +Контейнер не меняет clocks; постоянная host policy не установлена. Оба новых +runs работают в auto, в 22/27 samples ниже fixed-clock envelope. Низкая GPU +utilization не заменяет доказанное владение и не позволяет наследовать прежний +fixed-clock latency PASS. Ограниченный эксперимент с таким FAIL разрешён. + +142 focused tests PASS, ещё 42 adjacent regressions PASS. Один historical M4 +baseline test FAIL: существующие `.runtime` symlinks ведут в соседний checkout, +что отвергает неизменённый root-containment guard. Данные и тест не исправлялись +ради PASS. Ruff, mypy новых contracts, diff-check PASS. First failed setup и +нулевой run A сохранены: PowerShell array wrapping и отсутствующий pinned +preprocessing runner исправлены; восстановление сервисов теперь dependency-ordered. + +Evidence: `.runtime/perception-freshness-worker-20260902T1006MSK/manifest.json`, +140 artifacts, SHA-256 +`3b0a2ad32f6b60d3da48a4bcafdf6e11bc91209abc9d1f65da54b0eb36c52d45`; +одноимённая копия в `D:/NDC_MISSIONCORE/runtime/experiments/`. Полный отчёт: +[PERCEPTION_STREAM_STAGE1_2026-09-01.md](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md). +Четыре Mission Core сервиса восстановлены; Triton ready=200, старые service +loops не ремонтировались. Ollama/Frigate stopped/restart=no. Pilot containers=0; +GPU auto P8/210/405 MHz, 979 MiB, power limit 450 W. Mac 8000=200, 8765 закрыт. + +**Gate:** этап 1 завершён как контрактно-измерительный baseline. С учётом +прямого разрешения владельца развивать экспериментальную платформу при честном +overload FAIL — GO на этап 2. Это не обход real-time приёмки: новый профиль +всё ещё не qualified и не standalone. Дальше реализуем общий supervisor, +lease/data plane без полного source preload, per-cell aging и самостоятельный +image. EoMT не запускаем, новую модель не добавляем, старый UI/batch не +переключаем до соответствующих gates этапов 2–3; физический live/автономия не входят. + +### 0.14 Первый шаг этапа 2 — общий scheduler и per-cell freshness, 2026-09-02 11:00 МСК + +Сделано в коде, а не только описано: `bcacb02` выносит queue/serial GPU stage +из экспериментального пилота в общие perception modules. Пилот импортирует +тот же код; отдельного LAB-scheduler больше нет. DDRNet и RF-DETR выполняются +последовательно, CPU fusion может перекрываться со следующим GPU-кадром. +Ingress и готовый GPU-result делят две pending slots; active inputs сохраняют +учёт в 16 MiB до release владельцем. Cancel/error освобождают только свои +ресурсы; зависший callback удерживает владение до реального завершения. +Drop-history ограничен, totals считаются отдельно. Это ещё не controller lease. + +`1f8101e` добавляет исходные timestamps каждой TGS-ячейки, включённые в hash +результата. Publication и receiver адресно переводят старые ground cells в +rejected/NO_GO. Свежая часть карты больше не теряет весь допуск из-за одной +старой ячейки. Occupied/unknown не разрешаются; missing LiDAR/pose и stale +segmenter по-прежнему блокируют весь policy. TTL остаётся 250 ms. Время +старых данных не переписывается; derived consumer view проверяется своим +hash, исходные опубликованные bytes сохраняются. Повторная проверка не может +восстановить подавленное разрешение. На реальном использовании проверка нужна снова. + +| Новый последовательный Worker A/B | Whole-scene control | Per-cell | +| --- | --- | --- | +| Completed / drops | 128/128 / 0 | 128/128 / 0 | +| Latency mean / p95 / p99 | 82.74 / 125.01 / 130.31 ms | 77.52 / 123.91 / 136.17 ms | +| Fresh envelope при receipt | 25/128 | 76/128 | +| Missing sensor pairs | 52 | 52 | +| Исходные model/geometry/motion/TGS/material outputs | 128/128 exact | 128/128 exact | + +В per-cell варианте все 76 доступных source pairs дали свежий six-layer +envelope. **Это не означает, что внутри него все ячейки известны/свежи или +безопасны для движения.** 1994 ground cell×frame appearances истекли при +publication и ещё 201 при receipt; старые ячейки остаются NO_GO. Это счётчик +вхождений по кадрам, не 2195 уникальных препятствий. 52 missing sensor pairs +по текущему source binding не замаскированы. Все 256 derived receipts повторно +проверены: hashes, timestamps, mandatory layers и разрешения согласованы. + +Оба runs остаются latency FAIL по p99 >125 ms. Частоты auto гуляли, поэтому +разницу времени не выдаём за доказанное ускорение нового кода. Ничего не +разгоняли и не расширяли: Docker 8 CPU / 8 GiB, pending 2, inflight 16 MiB; +per-cell peak VRAM 2365 MiB, cgroup memory 3377.78 MiB, inflight 5,202,376 bytes. +Первый результат за 568 ms после stream start, warmup 9.36 s, stop 4.07 s; +остаток входных payload bytes после остановки — 0. Полный source заранее +не передавался/не хешировался, модели и thresholds не менялись. + +202 focused tests PASS; Ruff, mypy четырёх изменённых core modules и diff-check +PASS. Full suite и модели на Mac не запускались; ранее отмеченный historical +baseline failure с внешними evidence symlinks не исправлялся ради PASS. +Evidence: `.runtime/perception-stage2-cells-worker-20260902T1055MSK/manifest.json`, +125 artifacts, SHA-256 +`1a951fd9e807099e500fa66f8a40b1076071f96e4c8e0be4ab3094caaa33bf09`; +копия в одноимённой папке `D:/NDC_MISSIONCORE/runtime/experiments/`. +Четыре Mission Core сервиса восстановлены, Triton ready=200. Ollama/Frigate +exited/restart=no; pilot containers=0. GPU auto P8/210/405 MHz, 980 MiB, +450 W; Mac 8000=200, 8765 закрыт. Старые service loops не ремонтировались. + +**Gate:** принят первый инкремент этапа 2, не весь этап. Далее — общий +supervisor/StreamStart lifecycle, authoritative GPU ownership и fencing, +binary live ingress без знания длительности/EOF, затем самостоятельный image +без developer checkout/model mounts. Текущий diagnostic image с mounts не +называем готовым standalone Docker. Product LAB path пока не переключён; +этапы 3–4 не начаты, квалификация и actuation не разрешены. + +### 0.15 Lifecycle и владение Worker — 2026-09-02 12:00 МСК + +Следующий участок реализован и подключён к полному графу: `6acf468` добавляет +общий subprocess supervisor и Worker-local lease, `ac69e3b` — pilot integration +и реальные negative probes. Использованы прежние `GraphState`, `StreamStart` +и bounded scheduler, без нового LAB-приложения или смены моделей. + +Порядок: получить владение → загрузить/прогреть модели → Ready → допуск +кадров → последовательная GPU-работа и CPU fusion → проверенная публикация → +остановка процессов и освобождение входов → release. Проверяются все identities: +run/source/worker/epoch/generation, image/profile/config/calibration/clock. +Старый запуск не может продолжать вычисление/публикацию с новым binding. + +Владение защищено stable OS lock и durable ownership record на общем томе. +Истёкший lease сразу перестаёт разрешать новые операции; его нельзя оживить +поздним heartbeat. Но это **не** означает, что GPU уже свободен: следующий +владелец допускается только после реальной остановки процессов, активных +callbacks/threads и освобождения payloads. После crash остаётся `active`, +поэтому новый контейнер блокируется даже при освобождённом OS lock. Принудительный +takeover/удаление production marker не реализованы как способ продолжения. + +Граница доказанного важна: это cooperative ownership для управляемых runtimes, +использующих один controller-selected root на Worker. Legacy/unmanaged GPU +клиенты этим lock не управляются; перед модельными пробами четыре ранее +согласованных сервиса остановлены launcher’ом. В продуктовую очередь/постоянный +controller этот root пока не установлен. Heartbeat здесь локальный, не сетевой. + +На Worker последовательно проверены: + +- Другой контейнер получает `already owned`, пока holder активен. +- После чистой остановки следующий generation успешно запускается. +- После намеренного crash новый контейнер получает `previous owner unretired`. +- Полный normal graph: 128/128, 0 drops, 76 свежих envelopes; 52 source gaps + остаются NO_GO. Mean/p95/p99 = 83.12/124.98/136.12 ms. Порог p99 не пройден. +- Lease-loss A: 52 released = 51 completed + 1 `gpu-failed` terminal drop; + поздний GPU-result не опубликован. Lease-loss B: 50 released = 50 completed, + watchdog сработал между кадрами. Оба прогона честно помечены FAILED/lease-lost, + а не успешным укороченным replay. Unaccounted=0, процессов/active inputs после + cleanup нет, lease released только после проверенного освобождения. + +В final trace B запрос остановки был через 45.740515 ms после deadline, +retirement — через 4109.819258 ms. Последний receipt завершён за 4.527079 ms до +deadline; receipts на deadline или позже — 0. Это один bounded замер, не +обещание hard-real-time остановки в любых условиях. Lease 2 s, heartbeat 250 ms +и watchdog poll 50 ms — параметры пилота, не пороги безопасности беспилотника. + +Все 229 опубликованных model/geometry/motion/TGS/material результатов точны к +соответствующим reference prefixes; hashes/bindings/freshness/policy повторно +проверены. В normal VRAM peak 2363 MiB, cgroup memory 3407.88 MiB, inflight +5,202,376 bytes, first result 568 ms, warmup 9.36 s, stop 4.07 s. Модели, +thresholds, clocks, CPU/RAM limits не менялись. Runtime/controller overhead +не объявляется причиной разницы auto latency. + +223 focused tests, Ruff, mypy новых core modules и diff-check PASS. Full suite +и модели на Mac не запускались; старый historical symlink baseline failure +не менялся. Evidence: `.runtime/perception-stage2-lifecycle-worker-20260902T1146MSK/manifest.json`, +259 artifacts, SHA-256 +`00bd091a80845e50489a34ce4df2cbf3d2cd60d9ecb13d1d97accd03d44fdba4`; +копия в одноимённой папке `D:/NDC_MISSIONCORE/runtime/experiments/`. +Временные probe containers и два test lease volumes удалены после сохранения +owner records; production state не удалялся. Четыре сервиса восстановлены, +Triton ready=200, Ollama/Frigate exited/restart=no. Pilots=0; GPU auto P8, +985 MiB, 450 W; Mac 8000=200, 8765 закрыт. + +**Gate:** второй инкремент этапа 2 принят. Следом нужны binary live ingress с +неизвестной длиной источника, постоянная controller/backend-claim integration, +trusted recovery/inventory enforcement и самостоятельный image без developer +mounts. Mounted diagnostic image пока не является готовым переносимым Docker. +GO на этап 3 нет; network/full-session/quality/vehicle qualification не выдана, +actuation=false. + +### 0.16 Потоковый бинарный вход без знания конца записи — 2026-09-02 12:35 МСК + +`da60fef` добавляет общий binary IPC sender/receiver на основе существующего +`LiveIngressEvent`, без нового LAB-приложения или scanner feed. `a937400` +исправляет порядок фиксации End в испытании; `79ce55d` проверяет reuse прежнего +raw-first ingress и неизменность его wire v1. Всего 276 focused tests PASS. + +Рабочая граница: источник → ограниченные бинарные фрагменты → проверка binding, +порядка и SHA → raw consumer. Receiver не знает ни количества кадров, ни длины, +ни полного размера записи; End не нужен для начала доставки. 64-bit timestamps +в JSON metadata передаются decimal strings. Payload не становится PNG/base64, +максимальный fragment 1 MiB; raw camera event ≤1 MiB, LiDAR/pose ≤2 MiB. +Header ≤64 KiB. Open привязан к полному StreamStart и acquisition session; +каждый fragment/control — к тому же binding. Hash не заменяет authentication. + +Сырые буферы и reassembly теперь резервируются в тех же 16 MiB, что и +queued/active inputs. Cancel не освобождает чужие active bytes; lifecycle +дожидается callback/thread. При переполнении/timeout поток честно завершается, +а не растягивает source time или копит backlog. Gap/Unavailable/Cancel/End +явны; camera gap требует нового init. Проверка actual codec/keyframe/IDR +и decoder allocations остаётся следующим шагом. + +На Worker, CPU-only, без GPU request и без остановки постоянных сервисов: + +- 103/103 события: codec init, 32 исходных camera fMP4 chunks, 34 normalized + LiDAR increments и 36 poses. Все bytes/metadata совпали по независимым hashes; + original source timestamps сохранены. Каждый data channel доставлен до End. +- Источник выпускал prefix в исходном темпе 1×; max release lag 3.717 ms. + Полного source read/hash/decode до первого события нет. +- 4,061,693 wire bytes; peak input buffers 553,991 bytes, после stop 0. + Межпроцессный send-start → raw hash callback p95/p99 = 0.419/0.601 ms. +- Отдельный synthetic LiDAR оборван между fragments: started=1, incomplete=1, + completed=0; неполный payload не выдан. Lease/child/input resources освобождены. + +**Важно:** consumer в этой пробе только проверяет и хеширует raw события. +Ни DDRNet, ни RF-DETR, ни TGS здесь не запускались; sub-ms IPC не является +latency полного профиля или сети. Последний полный p99 136.12 ms остаётся +непройденным 125-ms gate. Самостоятельный Docker этим результатом не объявляется +готовым. Calibration у opaque probe явно synthetic/unused, не допуск model scene. + +Попытки 1230/1231 сохранены отдельно как rejected: сначала не хватило dependency +в diagnostic code pack, затем финальный timestamp journal гонялся с cleanup. +В принятом 1232 обе причины устранены и обе пробы повторены. Никакие старые +results/source files ради PASS не исправлялись. + +Evidence: `.runtime/perception-stage2-binary-ingress-worker-20260902T1232MSK/manifest.json`, +42 artifacts, SHA-256 +`2a5492080027a86de9f176f051c9265e29f377d1d9207c86ac93cdff7632505a`; +копия на Worker в одноимённой папке runtime/experiments. Rejected manifests +связаны из принятого. Ruff/mypy/diff-check PASS, full suite/build не запускались. +Временные процессы/контейнеры убраны; четыре Mission Core сервиса работают, +Triton ready=200, Ollama/Frigate exited/restart=no, Mac 8000=200, 8765 закрыт. + +**Дальше по этапу 2:** persistent incremental decoder + causal sensor adapter +подключаются к этому бинарному входу и тому же полному вычислительному графу. +После этого повторяется model parity/timing уже на новом пути, без чтения старого +concatenated camera file или готовой geometry. Network/gRPC/authentication, +постоянный controller/recovery/inventory и standalone packaging остаются +открытыми. Product LAB path не переключён, GO на этап 3 нет, actuation=false. + +### 0.17 Декодирование без готового MP4 и EOF — 2026-09-02 13:09 МСК + +**Принят ещё один инкремент этапа 2, не весь этап.** Общий parser выделен из +archive inspector без изменения его error contract. Новый decoder получает +только init и текущий fMP4 fragment: в нём нет source path, списка записи, +duration/frame count, предварительной склейки видео или ожидания EOF. + +Один persistent H.264 codec сохраняет состояние между фрагментами и должен +выдать ровно один native 800×600 BGR кадр текущего PTS. Проверяются первый +random-access/keyframe, непрерывность DTS, один sample и явные offset/size. +Неподдерживаемый layout/codec, B-frames, пропуск или неоднозначный результат +завершают этот decoder; нет скрытого fallback или выдачи будущего кадра как +текущего. Для другой камеры/формата потребуется явная проверка профиля. + +Последовательный CPU-only Worker A/B на 128 кадрах исходного 1× потока: + +| Проверка | Результат | +| --- | --- | +| BGR против прежнего pinned OpenCV decoder | 128/128 exact | +| Текущий кадр до чтения следующего fMP4 fragment | PASS | +| p95 первого per-fragment demux → direct sample варианта | 19.927 → 11.156 ms | +| p99 этих двух вариантов | 20.920 → 18.675 ms | + +Убрано повторное открытие/probing fMP4 на каждом кадре; NumPy импортируется до +readiness. Это ускорение **нового потокового декодера**, не прежнего полного +профиля. Готовый MP4 читался только отдельным reference-процессом для сравнения +пикселей; в новые decoder-прогоны он не монтировался. + +Проверка через существующий binary IPC: source process подаёт init + 32 camera ++ 34 LiDAR + 36 pose — всего 103/103 события без изменения bytes/metadata. +Декодер выдаёт 32/32 точных BGR. Первый decoded callback готов за 3.071 s до +End; последний кадр штатно дренируется до обработки End получателем. +Source-due → decoded/hash callback p95/p99 19.317/26.019 ms: **без** моделей, +geometry/TGS, scene delivery, сети и браузера. Пик общего input budget со +scratch/codec metadata — 5,727,751 bytes, остаток после normal/error cleanup — 0. +Обрыв между фрагментами даёт incomplete=1, payload не выдаётся, lease закрыт. + +PyAV18 установлен только в private experiment target и примонтирован read-only; +системные Python/Goose, модели, GPU clocks и постоянные сервисы не менялись. +Это ещё одна явная dependency будущего standalone image, не уже самостоятельный +Docker. Нативная память decoder измерена отдельно от Python input buffers. + +Коммиты `350366b`, `f102712`. 246 focused tests PASS; session/decoder повтор — +55 PASS, Ruff/mypy PASS. Все временные процессы/контейнеры остановлены; +Triton и Mac 8000 отвечают 200, 8765 закрыт; Ollama/Frigate exited/restart=no. +Evidence: `.runtime/perception-stage2-decoded-ingress-worker-20260902T1310MSK/manifest.json`, +43 artifacts, SHA-256 `612295eabbc8f203ad9b037a69ac9cf97b2df3134b087d9e51a9786738423f2f`; +он связывает отдельные decoder/reference/dependency manifests. + +**Следующий шаг:** supervised CPU decoder child с bounded RPC; causal cloud/pose +на момент camera release; передача decoded bundle в общий mailbox и тот же +DDRNet/RF-DETR/LiDAR-distance/motion/TGS/costmap/policy граф. Затем новый полный +parity/timing, без готового MP4. В этом probe sensor bytes только сохранялись, +не объединялись в scene; calibration identity синтетическая, model scene по ней +не допускается. Последний полный 124.98/136.12 ms и fresh 76/128 не изменились. +Этапы 3–4, controller/network, самостоятельный образ и product cutover ещё впереди. +Квалификации real-time или автономного движения этот инкремент не выдаёт. + +### 0.18 Полный граф на бинарном потоке — 2026-09-02 13:55 МСК + +**Теперь новый вход действительно питает весь профиль**, а не только декодер. +Исходные fMP4-фрагменты, нормализованные K1 points и pose поступают в исходном +темпе 1×. Нет предварительной передачи всей записи, её полного hash/predecode, +склейки камеры или `/source.mp4` mount. Source adapter пока читает существующую +запись внутри диагностического контейнера; новый физический/network adapter +этим не реализован. Decoder и consumer не получают path, duration или frame count. + +Цепочка: binary ingress → supervised CPU H.264 decoder → causal camera/cloud/pose +bundle → тот же DDRNet-39 GOOSE + RF-DETR + online geometry/расстояния + motion ++ TRAVEL TGS/costmap + advisory policy. Будущие points/pose не используются; +camera-time cut фиксируется до декодирования. Модели, пороги и правила не менялись. +GPU inference последовательный; одновременно другие полные профили не считались. + +Native decoder ограничен отдельным процессом и 1 GiB address space; RPC timeout +250 ms, вход ≤1 MiB, выход ровно 800×600×3 BGR. Raw, sensor cache и decoded buffers +имеют общий 16 MiB budget. При передаче в очередь ownership переносится атомарно; +два pending — общий предел, активные кадры не вытесняются. При timeout/ошибке +поток завершается, codec state не используется повторно вслепую. + +| Проверка полного 128-frame 1× прогона | Факт | +| --- | --- | +| Released / completed / drops / unaccounted | 128 / 128 / 0 / 0 | +| Входные события | 384/384: init 1 + camera 128 + LiDAR 124 + pose 131 | +| Первый результат / результаты до End | 583 ms / 126 из 128 | +| Полная задержка до локального receiver, p95/p99 | 161.974 / 191.806 ms — FAIL 125 ms | +| Decoder отдельно, p95/p99 | 10.871 / 11.606 ms | +| RPC+сборка bundle, p95/p99 | 18.053 / 38.991 ms | +| Peak accounted input / остаток | 8,883,895 bytes / 0 | +| Peak VRAM / RAM контейнера | 2,367 MiB / 3,314.648 MiB | +| Available sensor pairs / fresh scenes при получении | 76 / 74 из 128 | + +Источник не замедлялся под вычисления: release-lag p95/p99 = 2.375/6.263 ms. +Исходные 52 sensor gaps остались; ещё seq 106/107 устарели к receipt по geometry, +motion, costmap и policy. TTL 250 ms не увеличивали; отсутствующие данные не +подменяли «дорога свободна». Warmup 7.073 s, stop 4.074 s, все ресурсы освобождены. + +Parity: BGR, segmentation, detections, tracks, threats, raw TGS costmap, materials +и sensor binding/lineage совпали 128/128. Только два leaf-значения raw geometry +`range_m` (seq 13 / observation 3 и seq 29 / observation 2) отличаются от reference на +1.3877787807814457e-17 m. Поэтому **strict bitwise parity не объявлена пройденной**; +никакого нового tolerance или округления ради PASS не добавлено. Причину надо +воспроизвести отдельно; изменённые расстояния/качество модели этим не доказаны. + +Задержки снова коррелируют со снижением auto GPU memory clocks 10251→405–810 MHz. +Очередь p95/p99 = 44.284/84.492 ms, DDRNet RPC 73.068/77.479 ms. CPU quota throttling +не наблюдался. Это не controlled A/B с прошлым прогоном 124.98/136.12 ms: +нельзя объявлять всю разницу ценой нового транспорта или пределом 4090. +Peak VRAM около 2.3 GiB — память, а не «процент вычислительной загрузки». + +CPU-only oracle до GPU и после code review: 32/32 точных sensor bundles против +прежнего producer. Synthetic зависший decoder аварийно остановлен; released +cameras 0/1/2 учтены как failed, lease и память освобождены. 271 focused tests, +Ruff/format/mypy PASS. Нагрузки/моделей на Mac не запускали. + +Код `221e429`. Evidence: 161 artifacts: +`.runtime/perception-stage2-binary-graph-worker-20260902T1335MSK/manifest.json`, +SHA-256 `e224de4e9f2c5fd419fe0fb0b9be6e01ec267628568e104795ae211ec803bce4`. +Измеренный GPU snapshot сохранён отдельно от последующих cleanup/scratch +исправлений; последние перепроверены CPU-only, не выданы за новый GPU замер. +Четыре Mission Core сервиса восстановлены, Triton 200; Mac 8000=200, 8765 закрыт. +Ollama/Frigate остались exited/restart=no. Временный lease volume после сохранения +owner record удалён, записи/веса не удалялись; image не перестраивался. + +**Следом:** объяснить два numerical differences и продолжить снижение хвоста +decoder/IPC/queue/CPU-tail при воспроизводимом operating envelope. Затем закрыть +controller/admission/recovery/inventory, network и самостоятельную упаковку. +Текущий контейнер всё ещё использует явные code/model/PyAV mounts; он не является +готовым переносимым релизом. Старые LAB/registry/UI не переключены. Этапы 3–4 +не начаты; real-time, field quality, physical-live и автономное движение не допущены. + +### 0.19 Численное совпадение восстановлено, IPC облегчен — 2026-09-02 14:22 МСК + +**Полный граф на новом бинарном входе теперь дважды совпал с эталоном на 128/128 +кадрах, включая расстояния.** Два прежних отклонения не скрыты округлением: +причина воспроизведена на Worker без моделей и исправлена во входном буфере. + +Quaternion в wire-pose начинается после 24 bytes position. При адресе 8 mod 16 +NumPy 1.26.4 на текущем Worker округляет норму на один ULP иначе. Управляемая смена +только адреса одинаковых данных воспроизвела ровно прежние range differences. +Теперь quaternion имеет свою выравненную immutable 32-byte copy. Значения pose, +projection/дистанционная формула, модельные пороги и comparator не менялись; +никакого нового tolerance нет. Другой CPU/NumPy требует своей qualification. + +В decoder→parent→DDRNet убраны четыре лишние full-frame BGR copies: передаются +заимствованные memoryviews, framing не склеивается с копией всего кадра. +Владелец держит buffer до конца синхронной отправки; partial writes/ошибки +обрабатываются явно. Это сокращение CPU-копирований, не «полный zero-copy» и +не уменьшение числа байтов в сети. Source pacing 1×, binary ABI, limits и TTL прежние. + +Полный последовательный A–B–B–A при одинаковых штатных частотах: + +| Вариант | p95, ms | p99, ms | Raw parity | +| --- | ---: | ---: | ---: | +| Старый контроль A | 84.702 | 92.961 | 126/128 | +| Новый B | 85.113 | 91.219 | 128/128 | +| Новый B, повтор | 82.425 | 90.530 | 128/128 | +| Старый A, повтор | 83.930 | 91.759 | 126/128 | + +Во всех четырёх 128/128 кадров без потерь, 384/384 input events; полный MP4 или +предварительная передача всей записи не нужны. Модели GPU выполняются последовательно, +другие профили одновременно не запускались. Фактические clocks 2610/10251 MHz +на всём измеренном интервале; power limit и Docker quotas не повышались. + +Медианная накладная часть IPC стала примерно на 0.5 ms меньше у decoder и ещё +на 0.5 ms у DDRNet. Full p95 колеблется, p99 немного ниже; это небольшой выигрыш, +не «ускорили вдвое». Предыдущие 161.974/191.806 ms были при auto clocks, поэтому +разницу нельзя приписать удалению копий. Новый auto-clock run в этой итерации +не выполнялся; постоянную фиксацию частот не вводили. + +Available/fresh 76/128: исходные 52 sensor gaps сохранились и не подменяются будущими +данными. У кандидатов первый результат ≈580 ms, warmup ≈7.14 s, stop ≈4.06 s, +peak accounted input 8,761,039 bytes, после остановки 0. Пик VRAM 2363 MiB; +рост backlog укладывается в бюджет, CPU quota throttling не наблюдался. Локальный 125-ms +timing gate PASS не означает готовность к сети, другой/полной записи или полигону. + +CPU oracles 128/128 exact BGR/sensors; negative hung-decoder cleanup PASS; +279 focused tests, Ruff/format/mypy PASS. Код: `380b6ea`, `f39f1ff`. +Evidence: 305 artifacts, `.runtime/perception-stage2-ipc-worker-20260902T1410MSK/manifest.json`, +SHA-256 `9c72a93833a1dda51c4787dca13fb9791a1bf2e31c763b7740e1b21406703707`. +Сохранены и неудачный total tail CPU-canary, и все четыре полных прогона; +контроль не заменён только удачным кандидатом. + +GPU вернулся в auto, четыре Mission Core сервиса восстановлены; Triton/Mac 8000 +отвечают 200, 8765 закрыт. Ollama/Frigate по-прежнему exited/restart=no. +Временный lease volume удалён после сохранения owner record; записи и веса целы. + +**Далее в этапе 2:** controller/admission/recovery, непрерывная проверка GPU +operating envelope, сетевой контур и самостоятельный образ без code/model mounts. +Этот baseline достаточен, чтобы двигаться к эксплуатации профилей; общий +real-time допуск ещё не выдан. Старые registry/LAB/UI не переключены, +этапы 3–4 не начаты, управление моторами по-прежнему отсутствует. + +### 0.20 Controller readiness подключён к lifecycle — 2026-09-02 14:52 МСК + +Исторический инкремент. После уточнения владельца terminal-реакция на временно +неизвестную/просроченную telemetry заменена в TARGET на wait/resync; актуальная +граница нового режима и его интеграции описана в 0.21. Измерения ниже не изменены. + +**В общем runtime теперь есть постоянная проверка допуска к работе.** Перед +кадром, вычислением, возвратом результата и heartbeat проверяются владелец, +идентичность запуска и свежий Worker snapshot; watchdog делает это и без кадров. +При потере условий приём/вычисления прекращаются, собственные child processes +останавливаются. Новый профиль по-прежнему не получит lease до проверенного +освобождения старых процессов, callbacks и входных buffers. + +Разделены два режима. `strict-envelope` требует заявленные performance conditions +после warmup. `labelled-experiment` позволяет исследовать низкие clocks или +выход за измеренный envelope, но сохраняет нарушение даже после восстановления +условий и не выдаёт real-time допуск. Неизвестный/занятый GPU inventory, stale +telemetry, чужой owner/image/config и отсутствие warmup не допускаются ни в одном. +Низкая загрузка GPU сама по себе не является доказательством владения. + +Heartbeat не продлевает свежесть inventory, refresh inventory не продлевает lease. +Опоздавший refresh не оживляет остановленный запуск. Старый controller с другим +StreamStart не может изменить или отменить текущего владельца. У сенсорного +потока нет права объявлять GPU свободной; это отдельная доверенная control-plane +граница, без setter частот, управления сервисами или motor authority. + +Код `92625bf`, 349 focused tests PASS; Ruff/format/mypy PASS. На Worker последовательно +проверены четыре случая: strict low clocks, allowed overload, unknown inventory, +inventory expiry при продолжающемся heartbeat. Все PASS. Временный CPU-only +контейнер не имел доступа к GPU, моделям, записям или Docker socket. Остановка +CPU fixtures заняла 10.676–63.994 ms, input/children/heartbeat освобождены, +generation4 lease released. Это не время остановки полного GPU-профиля. + +**Важная граница:** GPU facts в этих четырёх сценариях синтетические. Реальный +Linux supervisor проверен, но continuous Docker/NVML collector и его доставка в +полный PilotController ещё не реализованы. Runtime без monitor явно сообщает +`enabled=false`; он не переименован в qualified. Предыдущие результаты полного +DDRNet/RF-DETR/LiDAR/TGS графа не пересчитаны и не расширены этой проверкой. + +Evidence: 86 artifacts, +`.runtime/perception-stage2-readiness-worker-20260902T1450MSK/manifest.json`, +SHA-256 `4588995d763fe82d896b42689e981f1d00feedaf9d6aab29f4579f771d03da3a`. +70 code files сверены с Worker. Сервисы и clocks не трогали; before/after IDs, +StartedAt и restart counts совпали. При этом у legacy agents уже были counts +21/2/2 — running не принимается за доказательство стабильной готовности, причина +в этом инкременте не исследовалась. Triton/Mac 8000=200, 8765 закрыт; +Ollama/Frigate exited/restart=no. Временный контейнер и fixture lease удалены; +сырьё, веса и прежние evidence не удалялись. + +**Далее в том же этапе 2:** настоящий read-only GPU/inventory collector и bounded +доверенный control-plane adapter, recovery, network transport, самостоятельный +образ без developer/model mounts. Четыре этапа не меняются; этапы 3–4 не начаты. +Полная передача записи не возвращена; режим 1×, модели/пороги/TTL прежние. +Общий real-time допуск, физический live и управление моторами не выданы. + +### 0.21 Обрыв входа не равен остановке профиля — 2026-09-02 15:30 МСК + +**Принятое поведение:** если пропала связь или задержались данные, прогретый +профиль сохраняется и ждёт. Replay clock продолжает идти 1×, а прошлые кадры +не складываются в очередь для последующего «догоняния». Когда вход восстановлен, +профиль принимает свежий keyframe/pose/points, сбрасывает старое временное +состояние и только после повторной проверки синхронизации возобновляет вывод. +Это не разрешение на движение: onboard stop/hold и правила физического resume +будут отдельным контуром; сейчас моторы/автопилот не интегрируются. + +Worker lease — локальное право одного запуска владеть GPU. Его renewal не должен +зависеть от Wi-Fi/GCS/ровера. При живом локальном controller потеря входной сети +не делает GPU свободной и не запускает другой профиль. Неизвестная/просроченная +GPU-телеметрия не доказывает конфликт: inference ждёт, но процессы сохраняются. +Подтверждённый чужой владелец, фактическая потеря локального lease, неисправный +child/decoder и явный cancel остаются основаниями terminal stop/recovery. +Отсутствие пакетов само по себе не доказывает, что K1 умер. + +**Что реализовано (`c31c46c`):** + +- Разделены resident activation и input epoch. После reconnect меняется epoch + входа, а lease generation и процессы сохраняются. Старые packets/results + отклоняются, pending input отбрасывается, активные buffers освобождаются только + после завершения их обработки. Новый профиль не может занять GPU поверх старого. +- `recover_input=True` включает waiting/synchronizing/active в общем lifecycle; + source clock должен быть сопоставлен локальному времени. Recoverable monitor + ждёт свежих facts без автоматического resume старой epoch. Параметры должны + входить в sealed effective config, а не скрытую настройку лаборатории. +- Decoder получил reset codec/DTS внутри того же дочернего процесса; sensor + window — сброс истории без роста memory budget. Resume требует свежий + реально декодированный keyframe, causal pose/points и callback temporal reset; + свежесть/epoch проверяются повторно после reset. + +**Что проверено:** 375 focused tests, Ruff/format и mypy — PASS. На Worker один +CPU-only container последовательно прошёл три input epochs. После EOF-пауз +150 ms и 2.2 s PID настоящего H.264 decoder и CPU sentinel не изменились; +декодированная картинка exact 3/3. Во время пауз synthetic source clock сделал +3 и 44 тика, local lease получил суммарно 54 renewals. Peak input 5,275,461 bytes, +в конце input/children=0, lease released, temporary container удалён. + +**Что ещё НЕ проверено:** здесь один реальный H.264 fragment повторён три раза +с synthetic timestamps/pose/points. Sentinel не является GPU-моделью, а reset +callback — не настоящий JointGraph/TGS reset. Полный PilotController и +BinaryGraphBridge пока работают в прежнем non-resumable режиме: их не объявляем +переведёнными флагом в общем классе. Нет нового full-GPU latency benchmark, +continuous GPU collector, внешнего network recovery или физического live proof. + +Следующее действие внутри этапа 2 — подключить recovery к полному профилю, +включая отбрасывание старых GPU/CPU outputs и сброс tracking/motion/rolling +geometry/TGS/costmap, затем проверить обрывы с сохранением настоящих модельных +PID. После этого остаются trusted collector/control plane, network и standalone +packaging. Четыре этапа не меняются; этапы 3–4 ещё не начаты. + +Evidence: 85 artifacts, +`.runtime/perception-stage2-continuity-worker-20260902T1518MSK/manifest.json`, +SHA-256 `fbd327d129c88caa13b7183b1ae2c4767e877a6f5472c0f430875cfd7401ed46`. +73 code hashes сверены с Worker и commit, sealed manifest сохранён на обеих +сторонах. Сервисы/clocks/quotas не менялись; legacy restart loops не исправлялись +и не объявляются здоровыми. Triton/Mac 8000=200, 8765 закрыт; +Ollama/Frigate exited/restart=no. Сырьё, веса и прежние artifacts сохранены. +Предыдущие full-graph exact128/128, conditional timing PASS, auto-clock FAIL и +source gaps остаются прежними. Общего real-time/autonomy допуска нет. + +### 0.22 Полный профиль переживает обрыв без перезапуска моделей — 2026-09-02 15:56 МСК + +**Теперь это проверено на полном GPU-графе, а не только на декодере.** Новый +режим подключён к PilotController, BinaryGraphBridge, GPU/CPU обработке и приёму +результатов. Во время разрыва профиль остаётся загруженным и сохраняет local +Worker lease; источник идёт по исходному времени 1×. Старые события не догоняются. + +При восстановлении ждём свежий keyframe и согласованные camera/pose/points. +Сбрасываются настоящий surface cache, tracking, motion, rolling geometry/map и +кэш сегментации. TGS считает каждый запрос без внутренней истории, costmap +перестраивается из нового rolling window. Triton/RF-DETR, DDRNet, decoder и TGS +сохраняют PID: нет повторного model load/warmup и второго активного профиля. +Результаты связаны с input epoch; старые данные не становятся новым решением. + +На Worker выполнены CPU-проверки и два повторения последовательных normal/gap +полных прогонов. Normal сохранил exact raw parity 128/128. В gap-run обработано +76 кадров, 52 намеренно пропущены при разрыве/ожидании синхронизации; каждый +кадр учтён. Старые history и timestamps ячеек после resume не обнаружены, +первая scene каждой новой epoch имеет свежие шесть слоёв; в паузе результатов нет. + +| Инъекция обрыва | Возобновление на исходном кадре | До первой свежей полной сцены от начала обрыва | +| --- | ---: | ---: | +| 150 ms на seq16 | 30 | 1.476 s | +| 2.2 s на seq72 | 110 | 3.857 s | + +**Важное ограничение:** связь восстановилась — ещё не значит, что уже есть +свежий результат. Дополнительное ожидание keyframe/sensors реально измерено; +эту доступность нельзя прятать за высоким FPS. Физический ровер должен иметь +собственный stop/hold и правила возврата движения; сейчас actuator integration +отсутствует. Actual CUDA/child failure и подтверждённый owner conflict остаются +terminal, они не маскируются как сетевой лаг. Обрывы в этом GPU-тесте пришлись +между compute calls; mid-compute discard проверен пока focused tests. + +Финальные p95/p99 обработки принятых кадров: normal 85.775/89.385 ms, +gap 83.163/89.729 ms. Это условный Worker-local результат при временных штатных +clocks 2610/10251 MHz, не общий real-time допуск; длительности пауз указаны отдельно. +Исходные sensor gaps и предыдущий auto-clock FAIL не отменены. Peak input <9 MB, +после завершения input/children=0 и lease released. + +Код `70927ea`; 383 focused tests, Ruff/format/mypy PASS. В review убрана лишняя +ссылка collector на предыдущий input; после неё оба full trials повторены. +Первый preflight был прерван до моделей из-за моего неверного нового 512 MiB +порога при известном idle baseline 534 MiB (факт 530 MiB). Этот abort сохранён; +проверка исправлена относительно baseline, не скрыта как успешный benchmark. + +Evidence: 330 artifacts, +`.runtime/perception-stage2-resume-worker-20260902T1545MSK/manifest.json`, +SHA-256 `a9449fa4c012e30ce8a06025790c0e110eeebab7c1859fdebf56d5e785961ea3`. +236 Worker snapshot hashes / 114 current source files сверены. Auto clocks и +четыре Worker services восстановлены, Triton/Mac8000=200,8765 закрыт; +Ollama/Frigate exited/restart=no. Temporary containers/lease volumes удалены, +recordings/models/evidence сохранены. Legacy restart loops этим не исправлены. + +Далее в том же этапе 2: настоящий trusted collector GPU/inventory и control +plane, внешний transport/recovery с отдельным budget доступности, standalone +packaging. Полный enabled pilot работает с recovery, но продуктовые очереди, +registry/UI и физический live ещё не переключены. Четыре этапа прежние. + +### 0.23 Реальная телеметрия Worker и ожидание её восстановления — 2026-09-02 16:52 МСК + +**Полный профиль теперь получает реальные факты Worker во время вычислений:** +GPU/driver/clocks, Docker image digest, настроенные CPU/RAM limits и перечень +других GPU-capable контейнеров. Сборщик работает на host, выполняет только +read-only запросы. Docker socket и права менять host в AI-контейнер не передаются. +Ответы приходят через отдельный read-only mount вне каталога записи результатов. + +Каждый запрос имеет одноразовый nonce и привязку к activation. Время наблюдения — +локальное время начала запроса, а не время прихода ответа. Поэтому старый ответ +не становится «свежей телеметрией» после сетевого/маршрутного лага. История +не накапливается: один pending запрос, ответ≤16KiB. Local lease продлевается +отдельным heartbeat; телеметрия не назначает владельца и не возобновляет lease. + +Read-only canary проверил три последовательных обновления с настоящими данными, +нашёл другой GPU-capable контейнер и не изменил сервисы/частоты. Затем последовательно +выполнены normal и delayed-reply проходы полного DDRNet/RF-DETR/LiDAR/TGS графа. + +| Проверка | Результат | p95 / p99 принятых кадров | +| --- | --- | --- | +| Без задержки |128/128, exact raw parity;50 обновлений telemetry,0 ошибок |91.157 /97.946ms | +| Ответ host задержан на2.2s |102 обработанных,26 пропущены без догоняния; resume seq50 |88.643 /91.236ms | + +Во втором проходе два запроса истекли по прежнему лимиту свежести1s. Runtime +вошёл в WAIT, сохранил четыре PID и lease, дождался новых фактов и свежих +camera/pose/points. Stores90/24/7/298 очищены до0/0/0/0; старых timestamps ячеек +и track history после resume нет. Первая новая scene свежая по всем шести слоям. +Между последней старой и первой новой scene прошло2.719s; после локального resume +до результата44.552ms. Это не вычитание Windows fault timestamp из Linux clock +и не общий network-recovery SLA. GPU/CPU phase в момент telemetry expiry отдельно +не записан — отмена работающего CUDA kernel этим не заявляется. + +**Граница доказательства:** scope `docker-gpu-access` не равен `host-compute`. +Windows выдаёт PID4/Insufficient Permissions, поэтому полный native host/WSL +process audit остаётся непроверенным. Scope включён в effective config и не может +подменить более строгий envelope. Unknown inventory/недоступная GPU telemetry +означают ожидание; подтверждённый конфликт — terminal. Low clocks допустимы только +как явно помеченный эксперимент, не real-time qualification. + +Первый GPU canary остановился во время warmup, до подачи кадров: PowerShell5 +превращал `$null` в пустой backup path для File.Replace, а startup adapter не ждал +восстановления телеметрии. Исправлены true-null вызов и warmup WAIT без уничтожения +загруженных children; первый abort сохранён. Порог1s не увеличен ради прохождения. +Normal/gap выполнены после исправления. Это не полноценный A/B-тест стоимости +сборщика; изменения p95 относительно прошлого запуска не объявляются регрессией +или улучшением без повторных контролируемых замеров. + +Код `61cbdb3`;404 focused tests, Ruff/format/mypy PASS. Evidence475 artifacts, +363 Worker snapshot hashes/115 текущих source files: +`.runtime/perception-stage2-worker-control-20260902T1630MSK/manifest.json`, SHA-256 +`aac125bd1b182d164c95d18089793fa54bf9797478bce1afe3de2a1d9093f6ef`. +Peak input8,761,039bytes, VRAM≤2366MiB, RAM≤3334MiB в этих bounded проходах. +После них input/children/collector threads освобождены, lease retired; temporary +containers/volumes/host collectors отсутствуют. Auto clocks восстановлены, +четыре Worker-сервиса запущены, Triton/Mac8000=200,8765 закрыт; +Ollama/Frigate exited/restart=no. Записи, модели и предыдущая история сохранены. + +Далее в том же этапе2: внешний бинарный data plane/auth и recovery через реальную +границу приложения–Worker, затем самостоятельная упаковка. gRPC остаётся первым +кандидатом внешнего транспорта, не уже реализованной сетью. Product registry/UI, +полноценный standalone, physical-live и управление ровером этим не завершены. +Четыре этапа и цель переносимых полных профилей не меняются. + +### 0.24 System/Worker и независимый экспорт runtime — 2026-09-02 17:37 МСК + +По отдельному запросу владельца расширена существующая страница Worker, без новой +навигации или карточек каждого процесса. Новая UI-интеграция каталога профилей +(этап3) этим не объявляется выполненной. + +Причины отсутствующей телеметрии подтверждены на действующем контуре: + +- Windows Telegraf остановлен, хотя StartType=Automatic. Application log показал + завершение MQTT output при недоступном брокере на старте. +- У MQTT-брокера сохранён bind192.168.68.52:1883, но фактического host listener не + было. Перезапуск того же брокера восстановил bind; TLS/public exposure не менялись. +- При возобновлении доставки проявился Timescale OOM: shared_buffers3490MB и + maintenance_work_mem1745MB против mem_limit1024MiB. Postgres был auto-tuned по + памяти Docker VM. Normalizer выполнял массовую очистку30-дневной истории внутри + MQTT callback, терял keepalive и провоцировал повторную нагрузку при recovery. + +Исправления: Postgres128MiB shared/64MiB maintenance/4MiB work memory; тот же +постоянный volume сохранён. Retention прежних30дней ограничен1000строк/минуту, +отдельной connection/thread и deadline2s/lock250ms. Не добавлена новая политика +удаления записей/результатов; исторические raw telemetry старше30дней по-прежнему +подлежат штатной очистке. Normalizer подключён через явный read-only local source +override существующего image; это не пересборка portable image. + +Telegraf теперь повторяет подключение MQTT, держит bounded2000metrics и flush2s. +Scoped credentials сохранены, конфиг/collector забэкаплены updater-ом в17:20:21МСК. +Остановленные контейнеры тоже отображаются: Frigate/Ollama остаются exited/restart=no. +Явный Apply broker исправляет исчезнувший listener даже при неизменном адресе; +read-only GET ничего не перезапускает. + +В System/Worker добавлены частоты GPU/VRAM и общий статус streaming-профиля: +running, waiting, synchronizing, stopped/failed; число процессов/ожиданий, +pending bundles и память входных буферов. Нет выдуманного idle/ready при отсутствии +данных. HTTP error/timeout очищает устаревший UI snapshot; poll продолжается. +Факт running у контейнера не означает готовность моделей. + +Продолжение этапа2: `RuntimeTelemetryPublisher` экспортирует один snapshot≤8KiB +раз в секунду в отдельном daemon, вне heartbeat/GPU callbacks. Опциональный +`--telemetry-snapshot` подключён к полному pilot. Host Telegraf читает файл≤5s +и использует прежний pipeline topic. Истечение файла выдаёт unavailable; +чужой legacy service не маскируется под новый профиль. Это только наблюдаемость: +нет lease renewal, GPU admission, sensor/result payload, MQTT credentials или +actuation. Fast host-control/readiness из0.23 остаётся отдельным контуром. + +Проверки:104Python PASS, Ruff/mypy PASS;703frontend tests, architecture4, +typecheck и production build PASS последовательно на CPU Worker (Node24.13.1). +Первая передача frontend fixture не включила plugin.manifest.json, затем исправлена; +PowerShell захватил Vite warning как terminating error, capture исправлен, итоговый +build завершён. Новый build установлен на canonical8000, прежний dist сохранён. +Mac memory pressure=2, swap около7.1GiB: по `mission-core-product-ui` дополнительная +браузерная нагрузка/визуальная приёмка отложена. UI visual PASS не заявлен. + +36-секундный CPU-only canary без моделей/GPU прошёл running → waiting → +synchronizing → running через тот же lifecycle; все состояния сохранены Timescale, +API trace подтвердил synchronizing и восстановленный running. Lease generation1, +360renewals, один новый input epoch,0export errors, clean release. Это не новый +модельный benchmark и не внешний transport camera/points. MQTT startup/outage +проверен отдельно: после18s без брокера агент оставался Running; после возврата +тот же PID9268 продолжил передачу. Первый checker ошибочно не пережил временный +health503; брокер восстановлен finally, исправленный повтор PASS. + +Final Worker:977MiB VRAM,0% GPU, auto210/405MHz,450W limit. Временный CPU container +удалён автоматически, isolated lease ушёл вместе с ним; snapshot canary перенесён +в evidence. Ни модели, ни Frigate/Ollama не запускались. Existing legacy perception +HTTP404/restart loops не починены этим изменением и не называются здоровыми. + +Evidence: `.runtime/worker-telemetry-20260902T1422Z/manifest.json`, SHA-256 +`825b1d8035dbf907b2b731d35ede4c5742b81e653a6f24670f4775981f853492`. +Source/exporter, Telegraf config, UI adapter и installed dist hashes Worker↔Mac +совпали. Следующие незакрытые пункты: визуальная проверка Worker после освобождения +памяти; затем внешний bounded binary stream/auth/recovery и standalone packaging. +Четырёхэтапный план/цель не менялись; этапы3–4 не начаты. + +### 0.25 Внешний gRPC/TLS binary candidate — 2026-09-02 18:11 МСК + +Добавлен общий сетевой адаптер, не новый LAB-сервис для конкретной записи. +`StreamingIngress` получает прежние raw события по gRPC небольшими бинарными +порциями≤64KiB; полная запись/архив/длительность заранее не нужны. Ответы имеют +ограниченную binary-оболочку поверх domain payload, без новой scene ontology. +TLS проверяет сертификат/имя сервера. Одноразовый256-bit grant выдаётся локальным +контроллером на30s admission и связывается с run/worker/profile/image/config/ +calibration/input epoch и acquisition session. На endpoint хранится только digest. +Ни сеть, ни payload не могут запустить модели, продлить GPU lease или сменить epoch. + +Сохраняются один активный поток, два pending ответа, отсутствие source backlog +и250ms deadline на целое наблюдение. Обрыв без End — WAIT, не завершение профиля. +Новый grant не заменяет проверку свежего keyframe/causal sensors у graph adapter. +Медленный получатель тоже не вызывает бесконечного накопления: таймаут доставки +закрывает текущий поток; модели/локальный владелец продолжают ждать. Зависший +trusted callback удерживает reservation и блокирует замену до своего завершения. + +Реальные находки и исправления: + +- Default HTTP/2 lookahead64KiB при отключённом BDP auto-growth не пропустил + событие1,048,595B за250ms по текущему SSH-маршруту. Fixed1MiB прошёл два повтора + без расширения deadline. Это настройка окна, не разрешение копить запись. +- Реальный slow-reader выявил, что даже отправка финального error status могла + зависнуть за непрочитанным ответом. Добавлен deadline и на этот путь; cleanup + перестал от него зависеть. Первые неудачи сохранены в инженерных evidence. + +Два CPU-only canary прошли16/16 SHA256-exact raw/reply. Финальный повтор на +актуальном коде: same-Mac RTT min/median/max14.360/23.919/120.815ms; обрыв2.202s, +тот же PID40 CPU sentinel, локальные renewals32→54. Peak mailbox6,750,559B, +RSS57,244KiB; после завершения0bytes, sentinel reaped. Это **не** FPS/latency +DDRNet+RF-DETR+TGS: моделей0, source clock и resume proof синтетические. Транспорт +шёл через TLS внутри существующего SSH, а не через квалифицированный канал ровера. + +Проверки:105 focused Python PASS,2 Worker-only проверки пропущены на Mac намеренно; +на Worker все20 transport tests PASS, включая1MiB output, real slow reader, +неверный TLS name/grant, replay старого доступа, malformed wire и late callback. +Ruff/format/mypy PASS. grpcio1.83.1/typing_extensions4.16.0 закреплены lockfile; +на Worker они установлены только в директорию этого эксперимента, не глобально. +Первый Worker pytest не имел typing_extensions; fixture dependency исправлена. + +Артефакты16шт: `.runtime/perception-stage2-grpc-20260902T1500Z/manifest.json`, +SHA256 `adf5eaf092feaed6721f66e2adaceded0cdbf55754e1f9953f54623bfb52d331`. +Source hashes Worker/Mac совпали. Все временные containers/listeners/SSH tunnels +закрыты; одноразовые private keys/grants удалены, public certs оставлены в evidence. +Final Worker982MiB/0%/auto210/405MHz/450W, Telegraf Running; Frigate/Ollama +exited/restart=no. Canonical8000 и телеметрия отвечают. UI/build не менялись; +Mac pressure вернулся к2, визуальная проверка не объявлена пройденной. + +Что дальше в том же этапе2: связать этот endpoint с существующим полным +`BinaryGraphBridge` и application-side source, подключить общие scene/layer +codecs и контролируемую выдачу grants/clock mapping; затем последовательный +full-graph normal/reconnect/slow-consumer canary. Текущий response cap1MiB +отклоняет более крупные payload: реальный размер слоёв/фрагментацию ещё нужно +проверить, а pending reply drops не заменяют полный delivery ledger. После этого +остаётся standalone packaging. Этапы3–4, full-session/physical-live и автономия +не закрыты. Цель переносимого полного Docker-профиля и четыре этапа не менялись. + +### 0.26 Полный graph через сетевой вход/выход — 2026-09-02 19:00 МСК + +Код и regression tests зафиксированы в коммите `6469505`; отчёт и ExecPlan — отдельной фиксацией. Push не выполнялся. + +Вынесены источник записи и приёмник результатов в отдельный CPU-only контейнер. +GPU-контейнер больше не получает camera/index/sensor recording mounts: только +модели, конфигурацию, калибровку и текущие developer dependencies прототипа. +Полный graph один; DDRNet и RF-DETR вызываются последовательно. Источник читает +camera fragments и нормализованные LiDAR/pose rows инкрементально в исходном1× +темпе, без предварительной передачи/разбора всей записи. + +Возвращаются не только хэши: настоящая512×512 uint8 маска, детекции, расстояния, +motion, grid coordinates, material/states, cell evidence и advisory policy. +Координаты grid входят в digest costmap. Проверки epoch/sequence/маски/шести слоёв +и свежести выполняются у приёмника; опубликованное доказательство не переписывается +при старении в пути. Прежний предел ответа1MiB не расширялся. + +| Финальные последовательные проверки | Normal128b | Gap128b | +|---|---:|---:| +| Исходные camera observations |128|128| +| Полученные mask + scene |128|102| +| Учтённые пропуски |0|26, sequence24–49| +| Drops выходной очереди / unaccounted |0 /0|0 /0| +| Input epochs / temporal resets |1 /0|2 /1| +| p95 /p99 до готового consumer-view |106.150 /115.349ms|107.098 /110.817ms| +| Максимум |126.910ms|117.317ms| +| Полная свежесть шести слоёв при assessment |76/128|58/102| +| Ответы до EOF источника |127|101| +| Максимальный output |459608B|460248B| +| Peak tracked / residual bytes |13217791 /0|13217791 /0| + +В normal один кадр превысил125ms; p95/p99 укладываются, но это не утверждение +«каждый кадр всегда до125ms». Отдельно записаны network arrival, завершение +проверки целостности и завершение построения consumer-view; таблица использует +последнюю точку. UI rendering/контроллер/мотор сюда не входят. Возраст проверен +на записанном assessment timestamp, а не искусственно освежён после вычисления. + +При намеренном обрыве2.2s source-clock продолжился.23 кадра пропущены источником, +47–49 пропущены при ожидании keyframe; продолжение —sequence50. Все четыре +resident PID сохранены, lease generation1 не менялась; одна очистка temporal +history, без догоняющего backlog. Между готовыми результатами23 и50 прошло2.725s: +это отдельная потеря доступности, не низкая latency принятых кадров. + +Normal:128/128 exact к предыдущему reference по masks, detections, метрическим +observations, tracks/threats, material, raw costmap и sensor lineage. Все230 +финальных scene совпали byte-for-byte с Worker publication и повторно проверены +по integrity/freshness/policy. Все230 decoded BGR hashes совпали с reference. +После gap segmentation/detections102/102 exact; зависимые от истории observations, +motion и costmap закономерно отличаются от uninterrupted run. Это reset/rebuild, +не обещание whole-scene parity через недостающие данные.52 исходные sensor gaps +обычного запуска остаются явно unavailable, не маскируются новым транспортом. + +Обнаруженные и сохранённые rejected attempts: неполный diagnostic mount pinned +DDRNet runner; отсутствие nested mountpoint в read-only каталоге; null ExitCode +в PowerShell launcher; лишний startup reconnect из-за init за2s до source start. +Последнее исправлено подключением за100ms до начала подачи, без увеличения +idle-timeout. Финальные normal/gap повторы имеют0/1 реальное восстановление и +ни одной transport error. Исходные пробы и ошибки не перезаписаны. + +146 focused tests PASS,2 больших Worker-only теста пропущены локально; Ruff, +format, targeted mypy и diff checks PASS. На Mac memory pressure2: без тяжёлых +build/browser/load. Peak VRAM2369/2372MiB, GPU-container memory3348/3369MiB; +shutdown4.067/4.065s. Замеры условны для stock clocks2610/10251MHz и450W, +GPU-контейнера8CPU/8GiB и CPU source2CPU/1GiB. Лимиты/частоты не повышались +относительно согласованного reference envelope. + +**Граница:** два контейнера одного Worker с проверенным общим Linux monotonic +clock. Не Mac↔Worker full-graph, не radio link, не hardware synchronization, +не physical live и не standalone image. Production grant delivery/startup retry, +межмашинный clock mapping, полный slow-consumer canary и устранение developer/model +mounts — следующие работы внутри этапа2. Этапы3–4 не начаты; LAB/registry не переключены. + +Evidence236 artifacts: `.runtime/perception-stage2-network-graph-20260902T1541Z/manifest.json`, +SHA-256 `d1bc7e26850a2d9050ee1d8f8a5ece2e6b8c53e2e7dba381cbd4445d68a5ec17`. +Подробный engineering report: +`experiments/perception/PERCEPTION_STREAM_STAGE2_NETWORK_2026-09-02.md`. +Временные container/network/lease удалены, ephemeral TLS key/grants удалены, +четыре прежних Worker services восстановлены, Triton healthy, GPU clocks auto. +Ollama/Frigate остаются exited/restart=no; Mac8000 и свежая Worker telemetry работают, +8765 закрыт. Автопилот/моторы/K1 не затрагивались; внешнего/Synology deploy нет. + +### 0.27 Межмашинные допуски и часы — 2026-09-02 19:42 МСК + +В коде добавлен TLS control endpoint рядом с бинарным двунаправленным потоком. +Клиент получает одноразовый data grant, уже выданный локальным контроллером +Worker. Он не получает права продлевать GPU lease, запускать/перезапускать +модели, выбирать epoch или выдавать motor commands. Сообщения ограничены8KiB, +проверены closed schema/activation identity, частота и один outstanding запрос. +Bootstrap capability передаётся отдельно один раз; data grants больше не требуют +копирования файлов по SSH. Пока это foundation/candidate, не новая продуктовая API. + +Часы сопоставляются четырьмя timestamp и диапазоном remote-minus-local, +без предположения одинаковой задержки туда/обратно и без правки OS clocks. +До16 свежих наблюдений; диапазон расширяется с возрастом, истекает через2s, +противоречие карантинит clock session. В эксперименте заданы условные бюджеты +500ppm относительного хода и50us ошибки каждого timestamp. Это не измеренная +аппаратная точность генераторов и не сертификат синхронизации. + +| Проверка на реальном маршруте Mac↔Worker006 | Результат | +| --- | --- | +| Clock probes с независимой проверкой арифметики |72/72 | +| Условная uncertainty min/median/max |3.883/4.469/27.118ms | +| Соответствуют неизменному бюджету5ms |60/72 | +| Synthetic source/reply SHA-256 exact |8/8 | +| Обрыв связи |2.202s; PID9 и lease generation1 сохранены | +| Local lease renewals за обрыв |136→158 | +| После завершения |owner released; resident reaped; residual bytes0 | + +Оба допуска доставлены через TLS Poll, второй имеет новый input epoch/token. +Старое сопоставление часов истекло во время паузы клиента2.3s и восстановилось +после новых probes. Clock-ready переключался и после warmup: нельзя взять один +успешный offset и считать его годным до конца записи. Необходимо непрерывно +контролировать uncertainty и при временном превышении ждать свежего входа с +новой эпохой, сохраняя модели и локальный lease. + +**Граница:** моделей0, один CPU sentinel, source clock/resume evidence синтетические. +Это проверка транспорта/допуска/часов, а не новый full-profile FPS или frame age. +Полный graph Mac↔Worker в этом инкременте не запускался: текущий full-graph adapter +ещё не переносит uncertainty в scene freshness и не ждёт восстановления clock mapping. +Порог5ms не повышен ради успешного отчёта. Ранее принятый полный graph внутри +одного Worker (0.26) остаётся действующим доказательством своей границы. + +252 local tests PASS,2 Worker-only skipped; финальные65 Worker tests PASS, +включая1MiB result/реальный slow-reader. Ruff/format/mypy PASS. +При overlap Exchange+Poll исправлен native accept-slot лимит gRPC: максимум3 +служебных RPC слота; data owner и GPU profile по-прежнему строго один. +81 исходный Python файл сверён с Worker. Evidence18 artifacts: +`.runtime/perception-stage2-control-clock-20260902T1635Z/manifest.json`, SHA-256 +`cd479c577fa3da78b1b01a6a90e03e8c742ecb53561e606d939408120a53a622`. +Код: commit `d7b8989`. [Подробный отчёт](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE2_CONTROL_CLOCK_2026-09-02.md). + +Worker CPU-проба ограничена1CPU/512MiB, без GPU/runtime=nvidia. Частоты и +постоянные сервисы не менялись. Один прежний perception-worker self-restart26→27 +зафиксирован: старый restart loop этим инкрементом не исправлен. Временные +контейнеры/18561 tunnel/listener/key/bootstrap удалены. Mac8000/agent-MQTT +работают,8765 закрыт. Frigate/Ollama остаются exited/restart=no. +Следом внутри этапа2: подключение continuous clock-readiness/uncertainty к +полному graph, последовательные Mac↔Worker/slow-consumer canaries, standalone. +Этапы3–4 не начаты; registry/LAB cutover, физический K1/live и actuation отсутствуют. + +### 0.28 Полный Mac↔Worker graph и отрицательная приёмка старта — 2026-09-02 20:37 МСК + +Код `35b6cd9`. [Подробный инженерный отчёт](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE2_CROSSHOST_GRAPH_2026-09-02.md). + +Полный профиль DDRNet-39 GOOSE + RF-DETR + online LiDAR/расстояния + motion + +TRAVEL TGS/costmap + policy-shadow получает исходный поток с Mac и возвращает +настоящие mask/scene/grid через gRPC/TLS по существующему SSH/Tailscale маршруту. +Запись читается инкрементально1×, без полной передачи архива; модельный контейнер +вообще не имеет mounts камеры/index/sensor recording. Это ещё диагностическая +упаковка с code/model mounts, не самостоятельный переносимый image. + +Worker теперь проверяет одноразовое подтверждение clock probe и сам строит +responder-side диапазон часов; anchor исходной записи неизменен. Условный envelope +500ppm/50us, expiry2s и предел uncertainty5ms не ослаблены. Свежесть всех слоёв +и ячеек costmap учитывает uncertainty; полный source→consumer age измеряется на +одних часах Mac. WAIT не освобождает GPU lease и не перезапускает модели. + +Исправлены три ошибки: повторное чтение меняющейся оценки часов внутри одной +проверки результата; EOF после преждевременного закрытия control endpoint; ранний +обрыв после выдачи grant, но до application OPEN, оставлявший владельца без входа +и без возможности выдать новую эпоху. Последний случай воспроизведён на Worker, +затем проверен12/12 раз; неподтверждённый malformed packet по-прежнему не может +остановить владельца. Начальный source anchor теперь создаётся после первого +локального clock handshake, но это ещё не барьер готовности обеих сторон. + +| Раздельные ограниченные попытки | Результат | +|---|---| +| canary32a/b | Ошибки упаковки: отсутствовали manifest и pinned DDRNet runner; не замеры | +| canary32c | 30 exact scene +2 compute discards; EOF error; p95/p99 consumer208.197/211.873ms, FAIL | +| canary32d | 0 результатов:3 source WAIT +29 sync skips; корректное завершение не является PASS | +| canary32e | Ошибка пути camera index в команде; вход не подан, bounded pilot завершён с освобождением lease | +| canary32f, финальный | 2 результата30–31;13 source WAIT +17 sync skips; все32 наблюдения учтены, FAIL | + +В финальном прогоне оба результата пришли после конца короткого source window, +143.881 и155.743ms. Это не достаточная выборка для FPS/p95/p99 и не прохождение +result-before-EOF gate. Оба результата fresh по250ms envelope, но доступность2/32 +неприемлема. Маски/детекции совпали с reference; history-dependent geometry/motion/ +costmap после пропущенного префикса не объявлены идентичными uninterrupted reference. + +78 clock observations,28 ready; uncertainty min/median/max3.915/5.312/30.808ms. +Первые13 кадров ждали допуска; ещё17 ожидали свежего keyframe/sensor proof, +resume на30. Не было «двух первых результатов, после которых всё остановилось». +Один lease generation1, четыре resident child PID, без reload во время ожидания. +Peak VRAM2365MiB, cgroup3313.4MiB, Mac source RSS59.9MB; это не предел24GiB4090. +Peak tracked input10479771B из16MiB; после закрытия0. Ответы≤403572B из1MiB. + +Проверки:297 local PASS/2 Worker-only skips;173 Worker PASS;12 дополнительных +early-reconnect cases PASS; Ruff/format/strict mypy/diff checks PASS.128 staged +Python files сверены поSHA256. Первые неудачные тесты и модельные попытки сохранены, +а не заменены успешными. Raw scene/маски/слои, same-Mac receipt age и учёт пропусков +перепроверены; полные raw clock exchanges ещё нужны для дальнейшей диагностики. + +**Следующий пункт этапа2:** разделить двусторонний clock warmup и фиксацию anchor; +подтвердить готовность Mac и Worker до начала1×. Текущий фиксированный2s lead +этого не гарантирует; потеря начального keyframe растягивает ожидание. После старта +clock записи не переносить и backlog не догонять. Затем короткий canary, и только +после его PASS — controlled cross-host outage/slow-consumer и более длинный поток. +Standalone остаётся далее в этапе2; этапы3–4, registry/UI cutover и физическое +управление не выполнялись. Не нужно маскировать протокольную проблему новой GPU. + +Временные контейнеры/volumes/collectors/tunnel18561 и private keys/bootstrap удалены; +leases released, четыре прежних service container IDs восстановлены, Triton200, +Telegraf Running, GPU auto210/405MHz,980MiB/0%/450W. Canonical Mac8000 PID33360 +и свежая identity-matched telemetry работают;8765 отсутствует. Ollama/Frigate +exited/restart=no. Записи, K1, моторы и внешний/Synology deployment не затронуты. + +Evidence `.runtime/perception-stage2-crosshost-20260902T1705Z/`,198 artifacts, +manifest SHA256 `7b435cac111b3e0e789aa137ba064651e6d344a5f8fb8fa35b0abbd0e7cb1d74`. +Все результаты — условные для stock-clock reference2610/10251MHz и текущего +SSH/Tailscale маршрута; не сертификат радио/бортового/live поведения. + +### 0.29 Совместный старт исправлен; измерен последующий clock WAIT — 2026-09-02 21:12 МСК + +Код `48835a0`. Mac теперь подтверждает каждый probe ещё до назначения времени +старта; Worker возвращает собственные clock bounds и принятый anchor. ReportClock +v2 строго проверяет activation/nonce/clock IDs/envelope, сохраняет точные integer ns. +Начало1× разрешено после готовности обоих clock windows, явного ACK Worker и data grant. +Потерянный ACK сохраняет тот же proposal; согласованный anchor не переносится. +Односекундный lead нужен только для доставки grant/setup, а не вместо проверки часов. +Неуспевший согласованный старт означает startup failure, не скрытое замедление записи. + +Один новый32-frame full-graph canary, без параллельных профилей и повторов: + +| Кадры | Результат | +| --- | --- | +| 0–5 | Получены шесть результатов; начальные camera/keyframe и sensor prefix не потеряны | +| 6 | Принят, затем учтённый compute discard `input-gap` | +| 7–15 | Девять source WAIT skips | +| 16–29 | Четырнадцать keyframe/sensor synchronization skips | +| 30–31 | Два результата после resync, оба после EOF короткого source window | + +Итого32=8+1+9+14, неучтённых кадров0. Source pace1× сохранён, p95/p99 source release +lag3.062/17.286ms.8/8 Worker→Mac raw payloads и маски точны; полностью свежих scene5, +до EOF6. До consumer-ready min101.345ms, median144.951ms, p95/p99/max215.767ms +на n=8 — FAIL, не квалификация стабильной производительности. Восемь masks/detections/ +material совпадают с uninterrupted reference; geometry/tracks/threats/raw TGS — только +шесть до gap. Два после resync имеют очищенную history; это не полный8/8 reference PASS. + +Все55 raw t1–t6 exchanges сохранены и пересчитаны независимыми integer формулами +для обеих сторон;41 joint-ready. На старте обе стороны ready и anchor единственный. +Затем samples27–35: conditional uncertainty5.031–5.667ms, выше прежних5ms. +На sample36 снова4.867ms. Worker WAIT864.139ms, keyframe resync дополнительно увеличил +разрыв результатов. Все RPC завершились успешно; host observations33/33 PASS, +телеметрия не истекала и владелец GPU не терялся. Lease generation1 и четыре +resident PID11/40/48/49 сохранились, temporal stores сброшены перед новым epoch. + +Эта uncertainty — расчётная граница при500ppm/50us, не измеренный физический drift. +RTT request/ACK включает scheduling приложения и транспорт: без дополнительного trace +нельзя назвать единственным виновником сеть, SSH, gRPC или event loop. Даже offline +все probes внутри прежних2s вместо последних16 не убирают эти девять FAIL samples. +Ни5ms, ни125ms, ни2s, ни темп источника ради PASS не менялись. + +Peak VRAM2363MiB, cgroup3341.08MiB, Mac source RSS61,767,680B; это не предел24GiB. +Полный DDRNet/RF-DETR/LiDAR/distance/motion/TGS/costmap/policy выполняется на Worker, +но пока в диагностическом образе с model/code mounts, без recording mount. Не standalone. +Проверен SSH/Tailscale маршрут, не будущий бортовой компьютер/радио/автономное движение. + +241 focused local tests PASS +2 Worker-only skip;198 Worker CPU tests PASS, Ruff/format/ +mypy PASS.129 измеренных source hashes совпадают с commit и code-v2 archive. +Session `.runtime/perception-stage2-joint-start-20260902T1805Z`, actual source start +18:04:32.831227Z;53 artifacts, manifest SHA256 +`9cb369fe7ae185d1a92f6050bc1018a878483f5eec169267f100843245428691`. +Подробный инженерный отчёт: +[Joint startup / increment16](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE2_JOINT_START_2026-09-02.md). + +Следующий gate этапа2: CPU-only attribution/A/B clock/control scheduling при передаче +и приёме scene, затем оптимизация подтверждённого источника jitter. После стабильного +короткого полного canary — controlled gap/slow-consumer, длинный поток и standalone. +Сейчас не запускаем длинную GPU-квалификацию на проваленном baseline и не ослабляем +admission. Этапы3–4/registry/UI/actuation по-прежнему не открыты. + +Temporary containers, collector, lease volume, tunnel18561, private key/bootstrap +удалены; lease released, четыре точных прежних service IDs восстановлены, Triton200, +Telegraf Running. Clock locks сняты, последующий automatic210/405MHz подтверждён, +power450W неизменен. Mac8000 PID33360/identity-matched telemetry работают;8765 отсутствует. +Ollama/Frigate exited/restart=no. Прежние defects legacy services не объявлены исправленными. +K1, моторы, исходные записи и внешний/Synology deployment не затронуты. + +### 0.30 Непрерывный полный LAN-canary32/32; задержка пока выше бюджета — 2026-09-02 22:06 МСК + +Добавлена ограниченная clock-only диагностика (`59a74a3`): TLS client/server, исходные t1–t6 и10ms event-loop scheduling witness. Она не выдаёт data grant, не получает GPU lease, не читает запись и не запускает модели. Lag не вычитается из clock bounds. Три последовательных CPU-only пробы по96 обменов выполнены без scene-трафика, по1CPU/512MiB/runc, без GPU. + +| Маршрут одного временного SSH-туннеля | Joint clock-ready | Непрерывно после первого ready | +| --- | --- | --- | +| A: существующий SSH/Tailscale |48/96|Нет| +| B: SSH по подтверждённому LAN |94/96|Да, после2 warmup| +| A2: возврат SSH/Tailscale |53/96|Нет| + +Строгая проверка того же host key сохранена. Tailscale preflight сам показал direct LAN endpoint; это **не доказательство обхода DERP/Интернета**. Менялся только адрес подключения отдельного запуска, не SSH config/роутер/firewall/продуктовый default. IP не зашит в модельный профиль. Все288 обменов и готовность обеих сторон независимо пересчитаны. + +Около100ms хвосты запросов остаются без моделей и scene: Poll p95 A/B/A2 88.838/92.403/89.950ms, ACK p95 LAN98.266ms. Максимальный Worker handler <0.257ms; максимальный наблюдённый loop lag Mac4.110ms/Worker2.040ms. Поэтому scene loop не является необходимой причиной, но точный виновник среди OS/gRPC/SSH/TCP/сети пока не установлен. LAN улучшил измеренный интервал готовности часов, а не доказал улучшение каждого latency tail или постоянный SLA. + +После CPU A/B/A выполнен **один**32-кадровый full-profile canary через LAN. DDRNet-39 GOOSE + RF-DETR + LiDAR/distance + motion + TRAVEL TGS/costmap/policy не изменены; обе модели исполнялись32 раза, без reuse/stride. Прежние129 runtime/test source files, веса, image и effective config byte-identical. Источник — исходный1× поток camera/points/pose, без полной предварительной передачи/декодирования и без старых perception-слоёв; model container не получает запись через mount. Один профиль/serializedGPU,8CPU/8GiB, временные штатные2610/10251MHz;450W не менялся. Образ всё ещё диагностический с code/model mounts, **не standalone**. + +- 32 released →32 accepted →32 byte-exact результата Worker/Mac. Все32 BGR/segmentation/detections/geometry/motion/material/lineage/sensor binding/raw TGS совпали с uninterrupted reference. +- WAIT, drops, sync skips, reconnect и source/clock RPC errors:0. Один anchor/epoch, lease1 и четыре resident PID сохранены.30 результатов до конца короткого source window; последние2 после EOF. +- Все50 full-graph clock exchanges пересчитаны: первые2 warmup, далее48 ready. Uncertainty публикаций3.645–4.771ms;5ms gate/2s expiry/16 samples/500ppm/50us не ослаблены. +- Source-due→consumer-ready на Mac: min86.598ms, median121.850ms, **p95/p99 205.864/213.751ms —125ms FAIL**. Результат прошлого8-кадрового sample не является парным latency benchmark для этих32 кадров. +- Доступны17 source sensor pairs, полностью свежих полученных scene только12. Пробелы/возраст исходных сенсоров и добавившаяся задержка обработки/доставки не скрыты.32 результата не означают32 пригодных актуальных расстояния/policy. +- Максимальный source release lag21.552ms; tracked input14,611,263B (<16MiB), peak reply440,369B. SampledVRAM2357MiB, cgroup3360.91MiB, Mac source RSS62,865,408B. Исчерпание24GiB не показано. +- Host-control:32 принятых наблюдения из33 запросов,0 expired; последний запрос pending в EOF snapshot, не33/33 accepted. После warmup envelope/input-pause violations нет; thread/collector закрылись. + +Worker-local compute-start→local receiver p95/p99 74.243/76.322ms. Это не время до Mac: network publication ставится в очередь до локального diagnostic parse/freshness. Разные p95 стадий нельзя складывать/вычитать как независимые стоимости. Worker-only accounting gates для внешнего источника остаются unknown/false; независимый joined verifier подтверждает32/32 и release lag21.552ms. Поля отчёта вручную не исправлялись ради PASS. + +245 focused local tests PASS,2 Worker-only skip локально;202 Worker tests PASS, Ruff/check-format PASS. Все131 измеренных Python source hashes совпадают. Evidence67 artifacts: `.runtime/perception-stage2-clock-route-20260902T1850Z`; manifest SHA256 `2645a0faacb89b5af5d3756feea05550a12cc64820be926d32f2103b5f225caf`. [Подробный отчёт](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE2_LAN_ROUTE_2026-09-02.md). + +Следующий результат **внутри этапа2**: per-frame source packing/write, Worker ingress/decode/queue/publication, result read/parse и наложение control requests. Сначала bounded CPU transport checks, затем оптимизация подтверждённой задержки и один короткий full-profile recheck. Не расширять5ms/125ms, не догонять backlog, не заменять модели вслепую. Controlled gap/slow-consumer и standalone остаются последующей работой этапа2; этапы3–4/registry/UI cutover не открыты, actuation=false. + +CPU/model containers, lease volume, collectors, tunnels, key/bootstrap удалены. Четыре прежних точных service IDs восстановлены; GPU auto210/405MHz,450W, Triton200/TelegrafRunning. Ollama/Frigate остаются exited/restart=no. Mac8000 PID33360 и identity-matched Worker telemetry работают;8765/18561 отсутствуют. Native-host GPU inventory/старые service defects не объявлены исправленными; физические K1/моторы и external deployment не затронуты. + +### 0.31 Крупный хвост локализован ниже приложения; оба узла оказались на Wi-Fi — 2026-09-02 22:35 МСК + +Реализована изолированная CPU-диагностика (`6af4c20`): ограниченные TLS-record witnesses по краям приложения на Mac и Worker. Они сохраняют только время/размер/offset/хеш зашифрованных записей, не расшифровывают поток и не пишут ключи, токены или содержимое. Это не новая обязательная прослойка production runtime. Диагностика не умеет запускать source/model, получать GPU lease или выдавать data grant. + +Три последовательные пробы по96 clock exchanges/192 RPC на одном pinned LAN SSH-маршруте,1CPU/512MiB/runc, без моделей/scene: + +| Вариант | Median RPC | p95 RPC | Max RPC | Запросов >50ms | +| --- | ---: | ---: | ---: | ---: | +| A: без свидетелей |9.789ms|96.093ms|116.939ms|13| +| B: свидетели на обоих концах |9.904ms|93.895ms|98.966ms|14| +| A2: снова без свидетелей |10.062ms|95.145ms|137.224ms|13| + +Добавление диагностики не устранило наблюдаемый tail; небольшая разница квантилей не объявляется ускорением. Все288 обменов часов независимо пересчитаны,5ms/2s/500ppm/50us пороги прежние. После startup readiness в этих коротких пробах непрерывен. + +В B сопоставлены424/424 encrypted records (211 request +213 response) и192/192 RPC с обработчиками. Worker handler: p95 0.190ms/max0.319ms; Worker TLS record→handler p95 0.473ms; handler→response record p95 0.121ms; Mac response record→RPC completion p95 0.649ms. Один начальный длинный запрос включает TLS startup без допущенного clock mapping — он сохранён как unknown для directional attribution. + +Остальные13 tails >50ms локализованы между TLS edges:8 на пути request,5 на пути response. Например, условные границы request84.236–93.023ms и response88.172–95.374ms. Это timestamps прикладного приёма/выдачи, не аппаратный wire/ACK trace. Не вычитать scheduler lag и не складывать/вычитать p95 разных выборок. Крупные camera/scene buffers этим CPU control proof ещё не измерены. + +Независимый прямой TCP-check к уже подтверждённому SSH22 Worker, без gRPC/Docker/forwarding/authentication:16/16 соединений успешны;7 пиков67.921–91.142ms. Эти интервалы измерены одними часами Mac. Native Worker→localhost:22: первый sample8.229ms, следующие15 —0.240–0.299ms.32 ICMP-запроса остались без ответа; это не объявляется общей потерей пакетов/смертью Worker, firewall не менялся. + +Read-only проверка интерфейсов: **Mac идёт через Wi-Fi en0, Worker — через Realtek8812BU Wireless LAN802.11ac USB NIC**. Reported866.7Mbps — link rate, не измеренный throughput и не гарантия малой задержки. Сейчас не доказано, какой именно radio/AP/OS/driver/power-saving механизм виноват. Не объявляем дефект конкретной карты или AWDL-причину. Полезный wired comparison должен убрать Wi-Fi на обоих концах; без согласованного физического подключения сетевые настройки не меняются. + +Вывод: один существенный источник tail уже воспроизводится ниже нашего pipeline. Замена DDRNet/RF-DETR или расширение VRAM этот факт не исправляет. **Это не доказательство идеальности всего runtime** и не новая квалификация full-profile: последний результат остаётся32/32, p95/p99 205.864/213.751ms FAIL,12 свежих scene. + +Следующая работа в этапе2 — per-frame packing/write, ingress/decode/admission, очереди GPU/CPU, publication/read/parse. В коде отдельно найден10ms polling готовых результатов; измерить его вклад и проверить event-driven замену с lifecycle/backpressure tests. Ethernet comparison при доступности уточнит сетевой дефект, но его отсутствие не блокирует оптимизацию/упаковку экспериментального runtime.5ms/125ms/source1× прежние; этапы3–4/registry/UI/actuation не открыты. + +82 local/82 Worker tests PASS, Ruff/check-format PASS. Все142 staged files/132 Python exact. Evidence43 artifacts: `.runtime/perception-stage2-tls-attribution-20260902T1923Z`; manifest SHA256 `abc3ac677b81e0d78f8d5891517022e33ac7fa962166bc399b4009ee48d87d8e`. [Подробный отчёт](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/PERCEPTION_STREAM_STAGE2_TLS_ATTRIBUTION_2026-09-02.md). + +Временные CPU containers/relays/tunnel/key/bootstrap удалены. Сервисы/GPU clocks/network settings не менялись; IDs/restart policies сохранены. Прежние m49 agent2→3 и perception worker18→23 увеличили autonomous restart counts — это отдельное наблюдение, не объявленное исправление. Ollama/Frigate exited/restart=no. Mac8000 PID33360/identity-matched Worker telemetry работают;8765/18561 отсутствуют. Нет новых GPU/full-profile запусков, K1/моторных действий или external deployment. + +### 0.32 Лаборатории сначала, эксперименты с профилями затем — 2026-09-02 + +Решение владельца заменяет прежний порядок realtime-first. Основной продукт: +запись K1 → совместимый ещё не рассчитанный профиль → «Рассчитать» → реальный +прогресс → проверенный immutable результат → просмотр кэшированной записи. +Расчёт может занимать больше времени, чем сама запись. Это допустимый +лабораторный анализ, но не доказательство realtime-пригодности. + +- Готовые профили уходят из списка расчёта в «Лабораторные доказательства». + Если готово всё, выбор пуст/недоступен, «Рассчитать» отсутствует, «Обновить» + остаётся. Старые версии/результаты сохраняются и открываются глазом. +- Кэш привязан к неизменяемой записи и точной версии definition/image/models/ + config/adapter/result contract. Совпадения имени недостаточно. Изменённая + версия доступна для нового расчёта. Compute-success без публикации не кэш. +- Повторный просмотр, refresh и выбор записи не запускают нейросети. + Failed/partial/missing-artifact не маскируются под готовый результат; + ошибку публикации повторяем без нового inference, где сохранился пакет. +- Сохраняем созданный streaming runtime, bounded buffers, явные timestamps, + leases и проверяемые результаты. Для полного recorded-analysis требуется + backpressure/сохранение временной шкалы; строгий realtime-rehearsal остаётся + отдельным режимом со своими прежними freshness/drop/deadline критериями. + Исходные sensor gaps остаются unknown, а не синтезированными расстояниями. +- Текущие portable definitions по коду: M4.9T5 — CPU-only TRAVEL TGS/costmap, + LAB V1 — EoMT + DDRNet последовательными стадиями. Ни один не объявляется + новым полным DDRNet/RF-DETR/distance/motion/TGS/policy Docker. Сохранённый + M4.9T5 viewer может объединять чужие исторические overlays; это не состав + исполняемого portable профиля. +- Один Worker/4090 — один профиль. Медленный EoMT сохраняется для экспериментов; + покупка GPU/бортового компьютера не блокирует лаборатории. Время подготовки, + прогрева, вычисления, передачи и публикации измеряем раздельно. Worker-local + compute FPS — только условный ориентир для такого же onboard hardware/config. +- После доведения workflow экспериментируем с конфигурациями и переносим + выбранный воспроизводимый образ на борт. Другая CPU/GPU архитектура требует + отдельной проверки/возможной сборки. Контроллеры, моторы и autonomy acceptance + пока вне scope. Никакого Synology deploy, новых LAB-микроприложений или удаления + прежних записей/результатов. + +Аудит текущего кода выявил незавершённую cache-связку: portable projector всегда +возвращает `existing_results=[]`, frontend decoder запрещает непустое значение, +selector смешивает исполняемые профили и архивные результаты. Исправление этой +связки — первый инкремент нового этапа 1, не уже выполненный полный acceptance. + +Первый code increment: portable submit теперь атомарно отвергает дубликат +того же active/reconciliation/pending-publication расчёта даже из другой вкладки. +Повтор с тем же ключом сохраняет идемпотентность; failed compute допускает +новую попытку. 88 focused tests, Ruff lint и mypy изменённых source files PASS. +Сам кэш, selector и progress пока не переключены; полного нового Worker run +не было, этап 1 остаётся открытым. [ADR 0050](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/docs/adr/0050-recorded-observatory-first.md). + +Проверка23:15 МСК: canonical8000 обновлён, PID55765, health/catalog HTTP200, +8765 отсутствует. Read-only SQL выявил старую блокировку claim-пути:50000 +receipts при лимите50000,49985 пустых опросов и15 выдач job. Последняя запись +2026-09-01T17:28:39.238Z;503 присутствовали в логах ДО текущего перезапуска. +Сейчас10 failed jobs,1 succeeded/not-required, активных/live jobs нет. +Готовность каталога не равна работоспособности Worker claim. Ближайший ремонт: +bounded idle polling/retention с сохранением идемпотентности и audit history, +затем готовый кэш/селектор. История не удалялась, лимит не увеличивался. + +### 0.33 Очередь Worker восстановлена без потери истории — 2026-09-02, 23:54 МСК + +Второй инкремент нового этапа1 выполнен: backend и оба действующих control +agents переведены на versioned claim/v3. Пустой запрос больше не создаёт +запись в журнале; фактическая выдача остаётся долговечной и защищённой от +повторной выдачи, смены capabilities и устаревшего владельца. + +- Все50000 прежних receipts (49985 пустых,15 выдач),11 jobs и остальные + старые таблицы сохранены: before/after canonical row SHA-256 совпали. + Сделана согласованная SQLite backup. Записи и результаты не удалялись. +- Новый ledger хранит только реальные v3 grants: отдельный конечный бюджет + 50000, общий storage bound128MiB прежний. Это не бесконечное увеличение + квоты: старые v2 receipts и их retry semantics сохранены без изменений. +- Для нового v3 idle тот же request ID может позднее получить работу; + для уже выданного grant повтор возвращает его же либо stale-claim error. + Старый сохранённый пустой receipt остаётся пустым даже при retry черезv3. +- Обновлён только реально импортируемый transport-модуль: одна строка + schema version в двух immutable control images. Модели, compute packages, + definition hashes, mounts и ресурсные ограничения не менялись. + Два диспетчера не означают два одновременно исполняемых профиля. +- 16 настоящих пустых запросов из новых агентов через Worker→Mac PASS; + capabilities=[] исключает получение модельной job. Фоновые опросы204, + v3 ledger0, оба агента running/restart-count0.126 focused tests и Ruff/mypy PASS. +- Canonical8000/PID57796 работает. Модели/GPU не запускались; Ollama/Frigate + остаются выключенными без автоподъёма. Временные контейнеры и диагностический + образ удалены; два прежних агента сохранены stopped/restart=no для rollback. +- Точные Docker create declarations нового control release — источник истины + транспорта; package manifests остаются источником истины вычислений. + Старый launcher, приравнивающий agent image к package image, для замены + transport overlay не использовать. Реальный reboot пока не проверялся. + +Ремонт пережил две остановленные проверки до cutover: сначала был проверен +неиспользуемый v1-файл базового слоя вместо фактического v2 import; затем +Docker не включил однобайтное изменение с прежним size/mtime в snapshot. +Обе причины проверены и исправлены, проверки не ослаблялись. Фактический +новый imported-source SHA81bdc27f… совпал с проектным v3 transport. + +Полное evidence, pinned images и rollback: +[OBSERVATORY_RECORDED_CLAIM_REPAIR_2026-09-02.md](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_RECORDED_CLAIM_REPAIR_2026-09-02.md). +Следующий шаг: verified published-cache projection по точной записи и версии +профиля, затем селектор и прогресс. Полного нового LAB-run в этом инкременте +не было. Этап1 и весь пользовательский цикл ещё не закрыты. + +### 0.34 Проверенный кэш результата — 2026-09-03, реализация и первоначальная пауза + +Третий инкремент этапа1 готов в коде и прошёл контрактные проверки. Это ещё +не сквозной расчёт записи и не включённая новая версия интерфейса. + +- Каталог сопоставляет точную запись/source snapshot и версию профиля с + successful/published job, Session provenance, полным immutable package, + центральным манифестом и всеми артефактами. Одного названия LAB или статуса + succeeded недостаточно. Идентичности моделей/image/adapter остаются частью + RunDefinition; старый результат не скрывает новую версию. +- Проверенный кэш возвращается как `existing / open-existing` и запрещает + повторный submit. Preflight не подготавливает raw source и не обращается к + моделям; сохранённый просмотр не требует доступного Worker. Строгий decoder + фронтенда принимает эту привязку через общий контракт, без LAB-микроинтерфейса. +- Отсутствие/порча любого артефакта, включая spatial evidence, не считается + готовым расчётом. Старые результаты не удаляются; возможность нового + расчёта возвращается. Подмена файла того же размера с восстановленным mtime + также проверена. Никакого автоматического запуска при Refresh. +- Большие файлы результата хешируются блоками1MiB при первой проверке или + изменении metadata; bounded memo4096 переиспользует результат проверки, + но каждый раз перепроверяет inode/size/mtime/ctime. Сырые записи не читаются + полностью ради каталога. Холодная проверка может занимать время дискового IO. +- Гонка с публикацией закрыта внутри queue INSERT. Большие файлы под write + lock не хешируются: если публикация новая/проверка ещё холодная, HTTP409 + просит обновить каталог, дубликат не создаётся. Старый idempotency key + сохраняет исходную job; подтверждённая порча допускает новый запрос. +- 120 focused backend tests,23 frontend/architecture tests, Ruff, mypy пяти + модулей и focused TypeScript check PASS. Все новые пакеты в тестах synthetic; + полный M4.9T5/LAB V1 расчёт и GPU-прогон не выполнялись. + +**Активация отложена по ресурсному правилу Mac:** memory-pressure=2, +swap~7.6–7.8GiB. Полная production build и browser QA не запускались; чужие +постоянные приложения/контейнеры не остановлены. Canonical8000/PID57796 +оставлен на прежнем согласованном backend/frontend release, health200. +Worker agents, модели, опубликованные данные и живая очередь не менялись. +Новый cache нельзя выдавать за уже работающую функцию в интерфейсе. + +После освобождения памяти: последовательные проверки/сборка, согласованная +активация на8000 и приёмка каталога без inference; затем этап2 — селектор, +прогресс и полный пользовательский цикл. Этап1 пока остаётся открытым. +[Подробности и воспроизводимые проверки](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_PUBLISHED_CACHE_2026-09-03.md). + +### 0.35 Память восстановлена, cache-инкремент активирован — 2026-09-03 + +Ресурсный blocker из0.34 устранён. После остановки владельцем лишних контейнеров +Docker VM с uptime23дня всё ещё имела footprint14GB, около13GB в учёте swapped/ +compressed, при12.5GiB доступной памяти внутри Linux. Это не14GB resident RAM +и не модельная нагрузка. Закрывать Chrome/Arc или отключать Little Snitch не +потребовалось; эти приложения и их настройки не менялись. + +С разрешения владельца сохранены48 container IDs/states/restart policies; +у12 выключенных Plane `always` временно заменён на `no`, Docker Desktop штатно +перезапущен, исходные политики возвращены без запуска Plane. Все45 non-Core +контейнеров сохранили состояния/StartedAt; image/mount identities неизменны. +Работают только3 прежних контейнера Mission Core, все healthy. VM PID9403→66297, +footprint14GB→1565MB, pressure2→1, swap7722→2746MiB. Лимиты14336MiB RAM/4096MiB +VM swap не менялись, данные/volumes/контейнеры не удалялись. В будущем Plane +может подняться при перезапуске Docker: его постоянный `always` сохранён. + +По resource gate скилла `mission-core-product-ui` последовательно прошли +architecture4/4, полный typecheck,714/714 frontend tests и production build. +Build15.38s, peak RSS2.26GB; memory pressure оставалась1, swap не рос. +Сборка подготовлена отдельно, прежний dist сохранён для rollback; затем +обновлены вместе frontend/backend через существующий LaunchAgent на8000. +Backend PID67747, UI `/assets/index-DSuuMkq4.js`, health200/reconciler ready. +Других backend/preview на8765/4173 нет; чужой launcher5173 не трогали. + +Проверены каталоги трёх записей:004TREE и00 совместимы с обоими portable profiles; +01 по-прежнему требует capture attestation, его не выдумывали. Точного нового +published cache hit сейчас нет: единственная succeeded job имеет старый +publication_state=not-required. Она не засчитывается за опубликованный результат +текущей версии. Оба новых индекса есть, row hashes всех6 queue tables сохранены: +11 jobs,50000 legacy receipts,1 reconciliation,0 live leases/v3 grants/preemptions. +Новых задач, модельных прогонов и публикаций не было. + +Встроенный браузер: реальная новая сборка, каталог/source, выбор portable M4.9T5, +Refresh, normal/expanded окно и Escape проверены; console errors/warnings0. +При этом воспроизведена незакрытая UI-ошибка: архивные entries смешаны с +исполняемыми profiles, а выбор jobs по source/setup без definition digest может +показывать старое «Расчёт завершён» рядом с новым «Рассчитать». Backend cache +не означает, что эта пользовательская логика уже выровнена. + +Следующий шаг на стыке этапов1–2: exact-version queue/status binding, селектор +только нерассчитанных profiles, прогресс и полный записанный цикл. Этап1 +пользовательски ещё открыт; положительный publish→cache→view пока подтверждён +synthetic tests, не новым полным LAB-run. Повторять memory/claim repair не надо. +[Подробности, измерения и rollback](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_PUBLISHED_CACHE_2026-09-03.md). +Private evidence: `.runtime/docker-vm-recovery-z1636o/` в рабочем checkout. + +### 0.36 Выбор только нерассчитанных профилей, без статусов завершения — 2026-09-03 + +По прямому уточнению владельца: **либо есть «Рассчитать», либо этой кнопки нет**. +Никаких «Расчёт завершён», «Результат опубликован» и заменяющих их плашек. +Готовый результат отображается внизу с маркером конфигурации профиля и +существующим действием просмотра. В dropdown — только совместимые текущие +portable profiles без проверенного опубликованного результата. Когда все +рассчитаны, dropdown пуст/недоступен, «Рассчитать» отсутствует, «Обновить» остаётся. + +Исправление реализовано в общем Observatory, без отдельных страниц по LAB: + +- Архивные entries больше не смешиваются с исполняемыми профилями. Название + старой лабы не скрывает новую версию; cache identity проверяется сервером. +- Jobs читаются по source/setup/definition SHA с фильтрацией до LIMIT. + Смена выбора не показывает предыдущие jobs/errors даже на один render. +- Во время уже принятого расчёта повторной кнопки нет; только индикатор ожидания. + До проверки допуска «Рассчитать» неактивна. Ошибки и повтор публикации остаются + отдельным сообщением/действием, не статусом успешного завершения. +- Все загруженные доказательства показаны без старого ограничения6. Существующее + ограничение окна каталога не отменено и не объявляется полной пагинацией500 записей. +- Публикация обновляет каталог результатов и выбор профилей; удаление projection + также вызывает перепроверку выбора. История, записи и артефакты не удаляются. + +Последовательные проверки:720 frontend tests,52 focused queue/API tests, +architecture4/4, typecheck, Ruff/mypy и production build PASS. Финальная сборка14.56s, +peak RSS2.11GB; pressure1, swap2666.19→2618.19MiB. Прежний dist сохранён для +rollback в `.runtime/observatory-selector-fQUwPT/frontend-dist-previous`. +Финальная runtime/UI-проверка описана в +[отчёте](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_PUBLISHED_CACHE_2026-09-03.md). + +Активировано на8000/PID69976, health200; UI `/assets/index-BHcT8phv.js`. +В браузере проверены оба профиля004TREE, пустой выбор01 без «Рассчитать», +все14 доказательств00, Refresh/Escape и normal/expanded окно; console0 errors/ +warnings. Найденное сжатие полей в узком окне исправлено существующей +адаптивной раскладкой по ширине контейнера. Технические логи старых failures +не показываются как ошибка нового выбора. +Row hashes всех6 таблиц очереди неизменны; новых jobs/публикаций/модельных +запусков нет. В реальных данных exact published cache hit пока отсутствует: +ветка «всё рассчитано» проверена synthetic tests, не выдана за новый полный LAB-run. + +Это не новый полный модельный прогон и не закрытие всего этапа2. Дальше — +реальные счётчики прогресса, последовательный полный расчёт M4.9T5/LAB V1, +публикация и повторный сохранённый просмотр без inference. + +### 0.37 Глобальный маршрут актуализирован — 2026-09-03 + +Сводка сверена с кодом `e436fb5`, evidence до `44afadb` и уточнением владельца +об отсутствии completion statuses. В этом ходе изменены только документы: +сборки, новые измерения, jobs, модельные запуски и изменения runtime не выполнялись. + +Основа этапа 1 реализована и локально проверена: очередь/claim, exact cache, +защита от дубликатов, source/setup/version binding, селектор и показ evidence. +Это не объявляет successful end-to-end run: его приёмка явно вынесена в этап 2. +На последней UI-проверке в данных не было нового exact successful/published +cache hit, реальные счётчики прогресса не реализованы. Старый +succeeded/not-required и готовые архивные overlays не закрывают новый цикл. + +**Ближайшее:**2A — режим полного recorded-analysis и настоящие счётчики; +2B — один полный M4.9T5 × RAVNOVES004TREE через UI до сохранённого просмотра. +Далее LAB V1, вторая запись, recovery/cache и постраничный каталог. Только после +этого — самостоятельный полный DDRNet/RF-DETR/distance/motion/TGS/policy-профиль +на базе уже сделанного streaming runtime, затем отбор и реальный борт. + +Не начинаем заново ремонт claim, памяти, селектора или LAN canary. Полнота, +качество и compute/transport metrics разделены; отсутствие remote realtime PASS +не блокирует лаборатории. Все четыре этапа, результаты и критерии — в разделе 17 +и [единственном ExecPlan](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md). +Прежние цифры/прогоны сохранены; исправлены устаревшие CURRENT/«следующий шаг». + +### 0.38 Реальный прогресс, публикация M49 и исправление кэша после рестарта — 2026-09-03 + +Код `bee8552`, установка контрольных агентов `54c8d82`, no-op reindex fix `bd947b4`. +Реальные bounded счётчики +Worker → backend → общий интерфейс активированы: фаза, число обработанных единиц +и знаменатель, когда он известен. Попытки разделены по owner/generation/sequence; +прогресс не продлевает lease и не меняет результат. Одна bounded строка на job, +без бесконечного покадрового журнала. Completion-кнопки/плашки не возвращены. + +726 frontend tests,128 focused backend/control tests и отдельно40 runtime/wiring +tests, отдельно3 installer tests; typecheck/build, Ruff/mypy и normal/expanded/ +dropdown-Escape QA выполнены. Для reindex-ремонта ещё89 session/publication и72 +admission/cache/queue/API tests; проходы пересекаются, суммы не уникальный total. +Все11 прежних jobs и50000 legacy claim receipts сохранены. Canonical8000/PID77997 +здоров после idle-only замены; прежний dist и SQLite backups сохранены. Модели, веса, TGS binary и определения +профилей не изменены; только8 Python-файлов наблюдения в двух новых контрольных слоях. +Остановленные предшественники сохранены с restart=no. + +Через обычную кнопку «Рассчитать» выполнен один M4.9T5 × RAVNOVES004TREE: +`observatory-run-b230216709dc4c59bc56c98c7e329bf1`, generation1. +Вход6837 members передан примерно за298с. Создан08:08:03.013Z, +опубликован08:31:39.776Z с первой попытки; весь цикл **23:36.763**. +Результат `m49-tgs-portable-review-a09d2b4a07d103e4f3693ba746a51be2197214768774eabfded4f109ae80dce4`; +package SHA `52e8afd6aaa38b615008463b873b94feae160946a69ce67aba12efc5f12b1589`. +Все10 центральных artifacts проверены по размеру/SHA. 6830 позиций camera-fragment +расписания,6811 доступных LiDAR association и19 UNOBSERVED. Учёт149733073 +rolling-point contributions сходится,0 unaccounted; это не число уникальных точек. +Расписание **39.215–757.160s**, camera epoch заканчивается757.260s — не все808.779s +исходной записи. Счётчики не доказывают покадровое декодирование всего видео. +TGS-only p95 **2.6075ms**, runner-stage p95 **29.99172ms**; это не latency полного +графа и не FPS будущего борта. JSON effective_fps относится к cadence источника. + +Первый контрольный рестарт обнаружил дефект: reindex менял служебный +`updated_at_utc`, входящий в source catalog hash, и готовый профиль снова +предлагался для расчёта. Код теперь сохраняет полный снимок при неизменных +session/source/artifact полях; реальные изменения продолжают менять identity. +Для этого результата восстановлено только одно служебное поле источника после +доказательства, что оно в точности возвращает исходный SHA всего снимка. +Сохранён SQLite backup; запись, sealed package, provenance и jobs не переписаны. +После исправления и рестарта каталог/job/документ совпадают с опубликованными: +M49 только внизу, в выборе только LAB V1. Повторного compute не было. + +**Важная граница:** portable review сейчас показывает JSON и10 artifacts, +а не синхронное воспроизведение camera/TGS. Поэтому2B целиком **не закрыт**. +Название «полный маршрут и воспроизведение» не заменяет visual/coverage proof. + +**Открыто:** полный versioned recorded-analysis и incremental input. Старый M49 +пока сначала получает всю запись и полностью декодирует LiDAR до replay-cache +lookup. Счётчики не устраняют этот барьер. Внутри camera archive/начального LiDAR +decode ещё нет byte/message progress. Неизвестные величины остаются неизвестными. +Следующий крупный блок — typed saved-data adapter общего проигрывателя: +камера именно этого источника + сохранённые TGS/costmap именно этого результата, +точная временная привязка, seek/play/pause и bounded чтение. Использовать уже +sealed пакет без нового запуска; старые E47/M49 overlays не подмешивать. + +Этап4 по уточнению владельца — будущий пункт: **сейчас на борт ничего не переносим**. +Полное evidence, declarations и rollback: +[OBSERVATORY_RECORDED_PROGRESS_2026-09-03.md](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_RECORDED_PROGRESS_2026-09-03.md). + +### 0.39 Сохранённый camera/TGS replay с Core — 2026-09-03 + +Код: Core packaging `2797985`, общий viewer `9db29bc`. + +Для опубликованного M49 × RAVNOVES004TREE из0.38 подключён общий native Rerun +проигрыватель: камера, исходное облако/траектория и сохранённый TGS в одном RRD +и на одной шкале. JSON больше не является единственным способом открыть этот +результат. Старый LAB V1 использует тот же переиспользуемый компонент, но свои данные. +Нового вычислительного прогона, замены моделей или вмешательства в Worker не было. + +**Откуда идёт кэш:** результат хранится/выдаётся Mission Core; Worker только считает +и публикует. Core один раз собирает производный replay, затем отдаёт тот же файл, +в том числе после рестарта. Браузер не обращается к Worker за просмотром. +Merged RRD: **193622178 bytes**, SHA +`012e9c2bdc20a06c5e2c748b8e3d149230fd1a3cf13ac15570c39a3555573a87`. +Холодная успешная упаковка116.950с; warm HEAD0.292с с первым SHA check и0.046с +при повторном доступе после restart/reopen. Это время ответа заголовков, +не время открытия Rerun и не FPS модели: браузер всё ещё загружает194МБ. + +Проверяются source/result/base identities, SHA, dtype/shape, clock и z bounds. +TGS map-gravity-local переносится в world ровно выбранной source pose, без +дополнительного вращения. Points/pose/trajectory остаются исходными. +6830 TGS anchors ×2244 cells,6811 LiDAR association и19 UNOBSERVED. +Диапазон39.215–757.160с, конец camera epoch757.260с, исходная запись808.779с. +Вне покрытия camera/TGS очищаются; пустота не означает свободный путь. + +Исправлен PTS-дефект нового video proxy: encoder time base округлял timestamps +до100мс даже с passthrough, получалось526 duplicate PTS. Исправленный вариант +использует demuxer time base:6748 decoded frames из6830 source packets, +0 duplicate/backwards PTS, max отклонение от source PTS222нс. Это не утверждение, +что каждый фрагмент дал декодируемое изображение. Старый LAB V1 proxy этим не исправлен. + +114 backend tests,728 frontend tests, architecture/typecheck/build, Ruff/mypy +и browser QA. Проверены play/pause, seek вперёд/назад, середина/конец покрытия, +Source/Local SLAM/TGS, camera modes,3D/PLAN, normal/expanded/Escape, restart/reopen. +M49 остаётся только в нижних результатах; текущий нерассчитанный LAB V1 — в выборе. +Кнопки «Расчёт завершён» нет. Canonical8000 сохранён; raw данные не включены в Git. + +**2B целиком пока не закрыт:** upstream Rerun0.36.3 активирует копию blueprint. +Смена portable-слоя применяется, но сбрасывает вручную изменённый ракурс. +Это явное ограничение, а не заявленное сохранение камеры. Поведение старых/Data/live +просмотров не расширено этим opt-in. Возврат PLAN→3D использует отдельный native +ракурс; первый following-eye применяется после initial seek, с native framing. +Начальный cursor portable replay ставится на1мкс внутрь первого sample, чтобы +не попадать на пустую latest-at границу. Timestamps исходника/камеры/TGS не сдвинуты. +Финальный browser recheck этой последней правки отложен: после сборки Mac держит +memory pressure2 при уже остановленных временных тестах/build/viewer. Пока +pressure не нормализуется, новый тяжёлый replay не запускается. +Дальше — поддержанный native-механизм сохранения eye либо отдельно согласованный +dependency upgrade, без самовольного WASM-форка/второго renderer; подробная +визуальная приёмка остаётся открытой. + +Также открыты2A incremental input/full recorded-analysis,2C LAB V1/вторая запись, +2D total disk-cache quota/eviction/recovery/каталог. Сейчас derivative cache имеет +размерные ограничения и free-space gate, но не общую LRU-квоту. Первая упаковка +ещё выполняется при открытии, не при публикации. Это не новый полный AI-профиль, +не доказательство realtime на борту и не допуск автономного движения. + +Подробное evidence: +[OBSERVATORY_SAVED_TGS_REPLAY_2026-09-03.md](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_SAVED_TGS_REPLAY_2026-09-03.md). +Отчёт опубликован через direct MCP в Ops: **MISSIONCOR-72**, +«Observatory — сохранённый M49 replay с Core». После первого transport error +проверено отсутствие карточки; подтверждённое создание не дублирует прошлый запрос. + +### 0.40 Lifecycle памяти Mission Core — 2026-09-03 + +**Правило владельца:** во время расчёта/просмотра операция использует необходимую +ей память; после завершения/закрытия/отмены/ошибки временные ресурсы освобождаются. +Не уменьшать ради этого качество, разрешение или облако точек и не удалять +записи/дисковый cache результатов. Little Snitch и другие пользовательские +службы не трогать. Общие «15 GB занято на Mac» не равны расходу Mission Core. + +Диагностика закрытого M49 viewer: renderer111 →1104 →567 MB спустя74с; +reload снижал до133 MB. Core168–170 MB, Docker VM2613 MB не росли вместе с ним. +Это локализованный browser lifecycle, не доказательство утечки всего backend. +В SDK0.36.3 найден продолжающийся panic-check timer; в backend — отсутствие +release blueprint-сессии при закрытии. SDK по ADR0045 не патчится. + +Добавлено: изолированный контекст прежнего upstream viewer, фасад публичного +API с обрывом ссылок на закрытый SDK/DOM/каналы, teardown на закрытие/pagehide, +восстановление после browser page cache. Сохраняются один renderer, одна шкала, +прежние controls; live source path не переведён в iframe. Backend получает +exact-owner release, idle TTL300с с renewal30с, очистку failed render/shutdown +и защиту от запоздавшего повторного создания уже закрытого владельца. +Это не остановка scanner/Worker при сетевом лаге и не удаление результатов. + +64 focused backend tests,734 frontend tests, Ruff/mypy, typecheck/build PASS. +Промежуточный iframe-вариант реально прошёл camera/TGS, play/pause, +normal/expanded/Escape и повторное открытие: GPU743 →369 MB после закрытия, +но renderer оставался790–810 MB. **Этот результат не принят как полный cleanup.** +Поэтому добавлен facade и после нормализации pressure выполнен финальный цикл: +renderer112 →1014 →829 MB спустя62с после closed snapshot; GPU365 →715 →375 MB, +Core162–164 MB. **Memory gate FAIL: браузерный остаток не устранён.** Открытие, +play/pause, expanded/Escape работают; на initial expanded кадре камера была +пустой до playback, её устойчивость тоже не объявляется принятой. Затем +pressure2, проверочная вкладка закрыта. Swap не рос:2013.75 →2005.75 MiB. + +Далее — локализовать retained native/WASM ресурс, а не повторять такой же +open/close и не принуждать GC/reload как «лечение». Затем оставшаяся visual +acceptance2B и incremental input2A. Холодная подготовка, +полный compute и публикация требуют отдельного lifecycle proof; текущая проверка +их не закрывает. Подробности и точные ограничения: +[memory report](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_MEMORY_LIFECYCLE_2026-09-03.md). +Core8000 после необходимого перезапуска работает, второй backend не запускался. +Ops MCP временно недоступен; обновление MISSIONCOR-72 не выполнено, локальные +документы актуализированы. Никаких внешних deployment/model runs в этой правке. + +### 0.41 Уточнение memory owner — 2026-09-03 + +Проверка прежней сборки с картой VM показала: первый закрытый просмотр834→215MB +за35с, крупные выделенные области действительно исчезли. Но повторный цикл +812→824MB за91с не подтвердил стабильность. GPU и backend освобождаются/стабильны; +конкретный retained-object root не доказан, memory gate остаётся открытым. + +В коде завершён primitive-only boundary v2: SDK objects, Error, native Promise, +подписки и каналы остаются внутри iframe. React получает простые данные через +JSON-строки; сохраняются один renderer/clock и прежние controls. Закрытие отменяет +pending parent start, завершает все каналы независимо от ошибок и повторно +останавливает поздно завершившийся native start. SDK не патчится, качество и +дисковые записи/cache не ограничиваются/не удаляются. + +15 focused tests и focused strict TypeScript PASS. Полный frontend suite/typecheck, +production build и browser memory acceptance v2 пока **не выполнены**: Mac +устойчиво показывает pressure2 даже после закрытия проверочной вкладки, swap +не растёт. По локальному resource gate тяжёлые проверки не запускаются. +Little Snitch/чужие приложения не трогались; временных viewer/build/test процессов +не оставлено. Core8000 healthy, но пока обслуживает **предыдущую сборку**. + +Далее при нормальном pressure: последовательно typecheck/tests/build, затем +normal/expanded/Escape и повторное open/close с footprint+VM map без forced GC +или reload. Не считать v2 принятой только по unit tests. После этого — остатки +2B/2A по плану. Ops read снова завершился timeout; карточка не обновлена. +Подробности — в том же memory report, новый evidence `observatory-memory-owner-UGy0AS`. + +### 0.42 Возврат к основному плану; текущая сборка проверена — 2026-09-03 + +По решению владельца основной приоритет снова полный лабораторный сценарий: +выбрать запись и профиль → рассчитать с настоящим прогрессом → сохранить → +смотреть из кэша без inference → повторить с другой записью/профилем. Требование +освобождать временные ресурсы после завершения сохраняется, но общая занятость +RAM Mac не превращается в отдельную бессрочную задачу. + +**Объективно: лабы целиком ещё не закрыты.** Этап1 реализован и локально проверен. +В этапе2 готов первый M49×004TREE compute/seal/publication/cache proof и общий +camera/source/TGS replay. Но ещё не приняты полный recorded-analysis без +whole-input barrier, стабильный visual replay, LAB V1/вторая запись, recovery и +каталог сотен записей. Этап3 — standalone полного графа — тоже не закрыт; +имеющийся прототип не переписываем. Этап4 остаётся будущим, не блокирует лабы. + +В текущем инкременте primitive-only owner v2 прошёл полные проверки и сборку. +Дополнительно исправлена потеря native pointer/Escape между iframe и внешними +controls: координаты divider передаются родителю, native canvas/clock прежние, +listeners снимаются при dispose. UI-композиция и качество данных не менялись. +16 focused tests,740 frontend tests,64 focused backend tests, полный typecheck +и production build PASS. Build15.14с, maximum RSS1994817536 bytes (~1.86GiB). +На8000 новая `app-DHVEqf5x.js`, backend89747 healthy без нового restart;8765 пуст. + +Новый тяжёлый M49 viewer **не был открыт**: browser auto-review отдельно отклонил +действие при pressure2 из-за риска прежнего остаточного footprint. Запрошено +разрешение на короткий просмотр; обхода запрета нет, temporary tab закрыта. +Visual/memory acceptance v2 не объявляется PASS по unit tests. Сборки завершились +без OOM, но swap за интервал финальной вырос1934.69→2173.69MiB — это не основание +обещать отсутствие memory pressure. Little Snitch/чужие службы/Docker limits +не менялись. Worker и inference не запускались. + +Проверены конкретные остатки основного плана: Observatory запрашивает первые100 +source и100 laboratory entries без продолжения cursor; LiDAR `_capture_arrays()` +выполняется до cache lookup. Исправление второго требует версии/сохранения exact +identity, не скрытой инвалидизации старых результатов. Эти работы не зависят +от разрешения на тяжёлый просмотр. Не возвращаемся к гонке за Wi-Fi latency. + +Следующий блок: остаток2A → завершение2B при разрешённом просмотре → LAB V1 и +вторая запись2C → recovery/каталог2D. [Сверка и evidence](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_MAINLINE_RECONCILIATION_2026-09-03.md). +Разделы0.40–0.41 сохраняют историю замеров, не текущий запрет продолжать весь план. + +### 0.43 Повторное использование входов установлено на Worker — 2026-09-03 + +Продолжен основной этап2A. Два действующих агента Worker теперь используют +общий дисковый кэш исходных файлов по SHA-256 и длине. Новая job/generation +сначала получает свой актуальный claim-bound manifest, затем восстанавливает +совпадающие файлы из кэша. Для частично готовой камеры передаются только +отсутствующие members, не весь архив. Кэш не заменяет admission и не смешивает +историю разных запусков. **Кэш визуальных результатов по-прежнему на Core**; +новый кэш на Worker нужен исключительно для подготовки вычислительных входов. + +M49 проверяет готовый LiDAR pack до повторного декодирования исходной записи. +Исторический producer не изменён; прежние pack IDs и manifest bytes сохранены. +На cache hit остаются потоковое SHA-чтение исходника и строгая проверка NPZ, +но raw decode повторно не выполняется. Повреждённые или несовпадающие входы +не принимаются. Временные файловые ресурсы и reader закрываются после операции; +качество, точки, кадры, модели и конфигурации не урезались. + +Изменение установлено в `ndc-observatory-m49-worker-agent` и +`ndc-observatory-installed-lab-worker-agent`; оба Running, RestartCount0, +restart=`unless-stopped`. Общий volume — `ndc-observatory-source-cas-v1`. +Прежние контейнеры остановлены, автоподъём отключён и сохранены для отката вместе +с точными declarations. Их нельзя запускать одновременно с replacements. +CPU/RAM/GPU/network limits, модельные packages и посторонние сервисы не менялись. + +Проверки:111 focused backend tests PASS, Ruff/mypy PASS. На реальном Worker +первый агент сохранил synthetic файл167936 bytes, второй восстановил точные +байты через общий volume в другой рабочий каталог. Это проверка общего кэша, +не замер FPS или полный прогон профиля. Тестовый файл и временные каталоги +удалены; записи, результаты и история не удалялись. Новых model jobs —0. +После установки очередь сохранила10 failed/2 succeeded, открытых live leases —0. +Core8000 healthy,8765 пуст. Little Snitch не трогали; тяжёлого browser QA не было. + +**Остаток2A:** первичная передача и подготовка новой записи ещё ждут полный вход. +Старые рабочие каталоги не импортировались в общий кэш массово; он наполняется +при обычной подготовке. Нужен версионированный recorded-analysis с ограниченной +инкрементальной подачей, полным учётом предусмотренных профилем результатов и +отдельными измерениями стадий. Warm reuse не является доказательством этого режима. +Далее — visual2B, последовательная матрица профилей/записей2C, recovery/каталог2D. +Полный standalone3 и будущий борт4 остаются отдельными этапами. + +[Отчёт, установленные image IDs, rollback и evidence](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_SOURCE_REUSE_2026-09-03.md). +Ops-карточка в этом инкременте не обновлялась. Разделы0.40–0.42 сохраняют +историю; новая установка не означает закрытие visual/memory acceptance. + +### 0.44 Обсерватория отделена от Legacy; постраничный каталог — 2026-09-03 + +Уточнение владельца: старые экспериментальные LAB остаются в Legacy +«Лабораторных контурах», но не смешиваются с результатами переносимых профилей +в Обсерватории. Ничего из архива, исходников или результатов не удаляем. + +**Установлено на8000:** в список попадают только результаты с подтверждённой +portable replay/publication identity. Имена LAB, дата и текущая установленная +версия не являются фильтром; прежние полноценные portable версии сохраняются. +У RAVNOVES004TREE остаётся новый рассчитанный M4.9T5 от3 сентября. Старый M49 +без replay capability и архивный canonical LAB V1 в Обсерватории не показываются. +У RAVNOVES00 больше нет14 исторических карточек E21–E26. Legacy endpoint до и +после изменения совпал побайтно; его UI/adapters не менялись. + +Закрыт и лимит первой сотни: новый opt-in page contract возвращает `next_cursor`, +Обсерватория последовательно дочитывает страницы каждого scope по100 metadata +entries. Поиск видит все загруженные источники. Старые API-клиенты получают +прежний ответ. Повторные/небезопасные cursors, дубли и HTTP errors не превращаются +в успешную неполную выдачу. Обход ограничен256 страницами на scope; достижение +предела явно помечается. Видео, облака и result artifacts при этом не загружаются. +Это keyset traversal, не транзакционный snapshot: новые записи во время обхода +попадут при следующем Refresh. Server-side текстовый поиск отдельно не добавлялся. + +Проверки:747 frontend tests,41 backend tests, typecheck, Ruff/mypy и production +build PASS. Fixture500 sources +102 LAB rows проверяет результат после первой +сотни и связь с source499. На действующем Core page size1 прошёл20 GET: +3 source/17 LAB rows →1 admitted result,0 unresolved, оба каталога дочитаны. +Browser: обычное/развёрнутое окно, поиск/смена записи, доступные профили, +Refresh без возврата Legacy и Escape выпадашки проверены. Модельный расчёт и +тяжёлый viewer не запускались; приёмка replay/memory этим не закрыта. + +Текущая сборка `app-9nK8VtbK.js`, Core PID1425 healthy на8000;8765 пуст. +Очередь сохранила10 failed/2 succeeded,0 live leases; новых jobs нет. +Предыдущий frontend dist сохранён для отката. Первый build упёрся в заданный +V8 heap limit1GiB; build с2GiB прошёл. Это не ограничение качества расчёта +и не изменение Docker/Mac limits; подробный ресурсный результат сохранён в отчёте. +Little Snitch, Legacy, GPU и посторонние службы не трогались. + +**По плану:** выполнена каталоговая часть2D. Остаются2A — холодная +инкрементальная подготовка и полный recorded-analysis;2B — visual/lifecycle; +2C — матрица профилей/записей;2D — остальные recovery/negative cases. +Standalone3 и будущий борт4 остаются отдельными этапами. Все лабы целиком +ещё не объявляются закрытыми. + +[Отчёт, проверки и evidence](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_CATALOG_BOUNDARY_2026-09-03.md). + +### 0.45 Сохранённый LAB V1 viewer и recovery; реальный canary не принят — 2026-09-03 + +Крупный проход по этапу2 выполнен, но не означает готовности всей лаборатории. + +**Установлено:** LAB V1 получил adapter сохранённых EoMT/DDRNet masks в общем +native viewer на Core. Проверяются source/clock, component hashes, taxonomy, +архивы и полнота; маски800×600 обрабатываются по одной без inference. M49 cache +сохранён, Legacy overlays не подмешиваются, отдельного LAB-микроприложения нет. +Сам visual replay LAB V1 на реальном опубликованном результате ещё не принят. + +Исправлена очередь публикации: старые exhausted/backoff ошибки больше не +закрывают доступ к поздним готовым результатам. Keyset pages по32, лимит на +реальную работу; interruption до/после publication восстанавливает тот же +package без второй job. История не удаляется. + +В оба Worker control-agent установлен bounded heartbeat retry: временный +transport failure повторяется с тем же generation/token/sequence в пределах +последней аренды; потерянный ACK не продлевает её сам. HTTP401/403/409 и смена +identity остаются отказом. Поздний/неопределённый ACK не даёт права публиковать +успех. Добавлена безопасная диагностика классов ошибок. Compute packages, +модели, лимиты и source-cache mounts не менялись. Прежние агенты сохранены +остановленными для отката; одновременно два владельца не запускались. + +**Реальный LAB V1 ×004TREE:** кнопка «Рассчитать» создала одну job +`observatory-run-67a6bf3e4d644e4a8ee3c03b915f8f01`, generation1, +`13:40:35.163Z`. Transfer около388s, prepare завершён, EoMT не завершён. +В `14:02:39.666Z` истекла аренда. Новый результат не опубликован. Точную +transport/отдельную executor-причину старый агент не сохранил; не объявлять +её доказанной перегрузкой4090. После независимой проверки отсутствия job +containers/attempt files штатный reconciliation сохранил job как failed, +с исходной причиной и immutable release receipt; SQLite backup сохранён. +Теперь11 failed/2 succeeded,0 live leases. Автоматического повтора не было. + +**Найден самостоятельный admission blocker:** в реально установленном EoMT +image требуется350GiB свободного остатка плюс полный рассчитанный рабочий +набор. При397474037760 bytes free минимум для6830 кадров —398758438400 bytes +ещё без входного видео. Это избыточный фиксированный reserve в нашем профиле, +не фактическая потребность модели в350GiB. Повтор без изменения политики +снова не пройдёт. Новая политика должна получить новую sealed identity; +подменять старый Docker/config под прежним digest или удалять пользовательские +данные ради этого floor нельзя. Его проверку нужно перенести до долгой подготовки. + +**Проверено:**749 frontend tests,166 backend tests, typecheck/build, Ruff/mypy. +Новый `app-w6onjKPq.js`, Core healthy на8000,8765 пуст. Browser fresh reload, +обычное/развёрнутое окно, Refresh и Escape селектора приняты: M49 внизу, +LAB V1 в выборе, кнопка «Рассчитать», без completion-плашек. Ранее отклонённое +тяжёлое открытие viewer не обходили; разрешение на ограниченный open/close +запрошено, visual/memory acceptance остаётся открытой. Это не возврат к +бесконечной оптимизации RAM и не запрет остальных работ. + +**Остаток:** новая disk policy/ранний preflight/диагностика LAB V1 → успешный +LAB V1 ×004TREE → оба профиля ×RAVNOVES00. Также открыты2A incremental cold +analysis,2B visual/lifecycle и long-outage recovery2D. Standalone3 и борт4 отдельно. + +[Отчёт, image IDs, rollback и evidence](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/experiments/perception/OBSERVATORY_SAVED_REVIEW_RECOVERY_2026-09-03.md). +Direct Ops не ответил за60s; карточка не обновлялась. Исходники, готовые результаты, +Legacy и Little Snitch не удалялись и не отключались. + +## 1. Исторический итог до решения 0.32 + +Разделы1–16 сохраняют снимки предыдущих итераций. Слова «сейчас», старые +GO-зависимости и названия этапов в них относятся к этим итерациям, кроме +явно помеченных уточнений2026-09-03. Актуальные CURRENT/маршрут/итог — 0.45, +17 и20. Не повторять старую работу и не переносить старый1× gate на recorded-analysis. + +Уточнение владельца от 2026-09-02 (МСК): глобальная цель — экспериментальная +платформа переносимых Docker-профилей для множества совместимых записей. +Концепция не меняется. Ближайшая работа сосредоточена на снижении задержек +runtime, копирований, маршрутизации, IPC/сети и оркестрации; не на управлении +физическим ровером. Тяжёлые модели и перегруженные конфигурации сохраняются +для сравнения и возможного переноса на более мощный Worker/бортовой компьютер. + +Лабораторная перегрузка допустима при ограниченных очередях/памяти, сохранении +исходного clock и явном учёте потерь/устаревания. Она не означает PASS real-time +и не разрешает actuation, но не блокирует разработку платформы или упаковку +полезного экспериментального профиля. 4090 — текущая измерительная площадка, +а не окончательный предел всех будущих профилей. Функциональная готовность, +качество восприятия и real-time квалификация фиксируются раздельно. + +В Mission Core Observatory появилась общая инфраструктура вместо обязательного нового микроприложения на каждую LAB. Однако полный standalone real-time профиль ещё не собран: сохранённый viewer, reusable graph и установленные portable packages имеют разный состав. + +Основной рабочий контур теперь разделяет: + +- запись физического оборудования; +- профиль того, как запись была получена; +- профиль моделей и их настроек; +- установленный неизменяемый Docker package; +- общую очередь заданий; +- Worker, который исполняет подходящий package; +- опубликованный результат и общий просмотрщик. + +Целевая продуктовая операция имеет следующий вид; нынешний package обеспечивает только часть этого пути: + +```text +выбрать запись + -> увидеть только совместимые профили + -> выбрать установленную версию полного профиля и effective mission config + -> поставить расчёт в общую очередь + -> подавать наблюдения потоком 1x на один выделенный Worker + -> получить инкрементальные результаты всех заявленных слоёв + -> сохранить отдельный проверяемый результат и performance/quality evidence +``` + +Для K1 это означает: можно создать сколько угодно записей и сколько угодно раз отправлять любую подходящую запись в один из поддерживаемых профилей без создания нового LAB-приложения. + +Последний полный прогон LAB V1: + +```text +job: observatory-run-ce7051ca3d1a4734aea9e3d2c34b0851 +source session: 20260828T130511Z_viewer_live +setup: lab-v1-eomt-ddrnet-portable-v1 +run definition: 269d71a24b4e63cff54e01273f9d4b35fc6cdd72bc6fadec206169ae0777e6ac +created: 2026-09-01T16:56:36.946Z +stopped: 2026-09-01T17:29:30.507Z +terminal state: failed after explicit operator stop +terminal detail: EoMT received SIGTERM, exit status 143 +publication: not performed +``` + +Прогон был остановлен намеренно, как только стало ясно, что текущий путь рассчитывает запись примерно час и тем самым нарушает исходный смысл экспериментов. Записанное видео должно заменять live K1 только как источник кадров. Оно не даёт права превращать real-time pipeline в многочасовой экспорт всех кадров. + +Итог для принятия решения: + +- общий package/queue/UI/Worker-контур сохраняется; +- текущий LAB V1 runtime **не принимается**; +- backend механически рекламирует package как установленный, но продуктовый статус профиля должен считаться `performance-blocked`; +- следующий новый прототип — DDRNet + RF-DETR + LiDAR + TGS, а не ремонт объединённого EoMT→DDRNet как целевого профиля; +- до полного прогона нужны streaming semantics, короткий canary всего состава и обязательный realtime acceptance gate; +- публикации и нового результата этого запуска нет. + +--- + +## 2. Какая исходная проблема закрывается + +Старый подход связывал каждую лабораторию с собственным набором скриптов, окружением, способом запуска, UI-веткой и конкретной записью. + +Это создавало неправильный цикл: + +```text +новая запись + -> новая ручная LAB-разработка + -> отдельное микроприложение + -> новый специальный запуск +``` + +Целевой цикл, частично поддержанный текущим control plane, но ещё не доказанный для нового полного runtime: + +```text +новая совместимая запись + -> выбранная версия полного Perception-профиля + -> существующий установленный package + -> общая очередь + -> новый immutable result +``` + +Новый полный профиль должен добавляться один раз как отдельный версионированный образ и контракт. После квалификации его можно применять к любому количеству совместимых записей. Будущий live выбирает тот же образ и effective configuration; одно название при разных исполнителях не обеспечивает эквивалентность. + +Новое оборудование должно добавляться отдельно через EquipmentModel и CaptureProfile. Появление нового устройства само по себе не делает старые модельные профили совместимыми с его записями. + +--- + +## 3. Что сейчас является единицей переиспользования + +Единица переиспользования — полный Perception-граф, а не страница, исследовательский каталог или одна голая модель сегментации. + +Ею является точная связка: + +```text +RunDefinition + + model releases + + standalone profile image / executable graph + + resource policy + + source requirements + + effective mission/equipment configuration + + timing/freshness/performance contract + + result contract + + publication contract +``` + +После сборки эта связка получает точные identities и устанавливается на Worker как независимый package. + +Для исторического LAB V1 установленная связка включает две последовательные стадии; это CURRENT, не новый TARGET: + +1. EoMT Cityscapes Large 1024. +2. DDRNet-39. + +Текущая package-реализация запускает модели целыми стадиями: сначала всю запись через EoMT, затем всю запись через DDRNet. После проверки реального job это решение признано неверным. Более того, в этом исполняемом составе отсутствуют detector, LiDAR association/ranging, TGS и threat graph. Новый полный профиль не должен наследовать это урезание функций. + +### 3.1 Recorded-analysis и исторический realtime-rehearsal + +**Уточнение2026-09-03:** рабочий режим Observatory — полный recorded-analysis: +исходные timestamps/причинность сохраняются, медленный Worker регулирует +скорость подачи через ограниченные очереди, обязательные кадры не теряются +ради wall-clock1×. Полный output сохраняется для просмотра. Realtime-rehearsal +остаётся отдельной квалификацией того же runtime, с прежней freshness-политикой. +Это версионированные режимы, не глобальное ослабление live-контракта. + +Ниже сохранён прежний realtime-first контракт и числа. Они относятся только +к историческому rehearsal, не являются текущим gate этапа2 Observatory: + +Записанная сессия — это замена live transport, а не разрешение на offline batch. + +Правильная семантика: + +```text +recorded K1 frames with original timestamps + -> speed 1.0 replay + -> bounded queues + -> configured multirate sampling + -> warmed model inference + -> timestamped outputs without look-ahead +``` + +Ранее зафиксированные в разных экспериментах performance contracts дают следующие ориентиры. Это исторические параметры разных составов/источников, не готовый контракт нового профиля и не разрешение запускать EoMT с DDRNet вместе: + +- replay speed: `1.0`; +- streaming without look-ahead: обязательно; +- maximum wall over ideal: `1.08`; +- semantic sampling: каждый пятый кадр; +- minimum semantic rate: `1.8 fps`; +- DDRNet vegetation timeline: `12 Hz`; +- DDRNet inference: `6 Hz`, stride `2`; +- minimum DDRNet effective inference: `5.604534 fps`; +- DDRNet completion p95: не более `125 ms`; +- bounded source buffers; +- full-route RGB prefetch: запрещён; +- full semantic output persistence: не требуется для runtime. + +Следовательно, «реал-тайм» не обязательно означает прогон каждой модели по каждому кадру. Он означает явный согласованный schedule, ограниченные очереди и выполнение freshness/deadline contracts всего профиля. При этом каждый обязательный слой действительно рассчитывается и отдаётся, а удержанная маска не считается новой. + +Эти числа нельзя переносить механически: 6830 кадров / 808.779495667 s / stride 5 дают примерно 1.689 semantic результата/s, меньше старого minimum 1.8. Численные критерии первого полного профиля замораживаются в этапе 1 по его входному потоку и составу. Старые 12/6 Hz и phase offset — исходная точка измерений, не обещание нового end-to-end результата. + +--- + +## 4. Текущие пользовательские профили + +### 4.1 M4.9 TGS portable v2 + +Статус: + +- профиль существует; +- совместимость с K1-записями вычисляется сервером; +- задача исполняется через durable queue; +- живой результат ранее успешно опубликован; +- историческая result projection сохранена в Observatory; +- Worker пока остаётся переходным profile-specific агентом. + +Уточнение2026-09-03: на последней UI-приёмке сохранённая M4.9 projection004TREE +не имела admitted действия просмотра; единственная succeeded job была +not-required, а не новым verified published cache hit. Полный новый путь +публикация → review/cache относится к приёмке2B, не считается уже выполненным. + +Это доказанный ранее CPU-only TGS-профиль с ограниченным result contract, не полный AI-профиль рига. В его portable definition `models: []`. Перенос на общий агент — отдельная миграционная задача; он не является обязательным предварительным условием создания нового standalone Perception-профиля. + +### 4.2 LAB V1 EoMT + DDRNet portable v2 + +Статус: + +- точный package собран; +- все его образы и статические модели существуют на Worker; +- offline validation завершена успешно; +- package установлен и активирован; +- generic agent запущен; +- backend получает точную capability-рекламу; +- выбранная K1-запись признаётся совместимой; +- профиль показан в UI и допускает постановку в очередь; +- полный запуск создан реальной кнопкой интерфейса; +- prepare и EoMT реально стартовали на Worker; +- текущая реализация не выдерживает performance semantics; +- job остановлен до DDRNet и публикации; +- профиль **не готов к пользовательскому использованию**, несмотря на технический `ready` в capability API. + +### 4.3 Что на самом деле объединяет M4.9T5 viewer + +Скриншот M4.9T5 показывает собственные TGS-ячейки, отдельный сохранённый M4 detector/geometry/threat result и E47 semantic archive с заранее вычисленными EoMT masks. Их показ на одной временной шкале не означает, что один контейнер выполнил все слои online. Расстояния и классы не фиктивны, но вычислены в связанных результатах других проходов. + +Отдельный RF-DETR reference graph действительно содержит detector, LiDAR association, temporal, motion, rolling map и threat. Сохранённый integrated shadow с CPU TGS сообщает 4489/4489 frames, 11.860865 FPS, p95 совместной готовности 46.825886 ms, p99 63.94485 ms и TGS p95 1.735 ms. Это реальное историческое свидетельство вычислительной ёмкости, но не новый полный профиль: TGS не меняет graph state, combined timing соединяется из журналов после прогона, а geometry использует подготовленный local-surface pack. EoMT-сегментация не входит в этот измеренный проход. + +### 4.4 Новый standalone профиль + +Утверждён состав из раздела0.2. Уточнение2026-09-03: полный online graph/runtime +уже реализован как инженерный прототип и проверялся короткими canary +(0.6–0.31); начинать его заново не нужно. Не приняты самостоятельный продуктовый +образ и полный recorded-analysis run этого состава в общем лабораторном цикле. +Все обязательные выходы должны вычисляться заново в одном запуске на любой +совместимой записи. Точный класс «столбик» и разделение дорог/тротуаров не нужны. + +--- + +## 5. Оборудование и профиль записи + +В систему введено явное различие между физическим типом оборудования и профилем захвата. + +### 5.1 EquipmentModel + +Текущая зарегистрированная модель: + +```text +xgrids.lixelkity-k1 +``` + +Она описывает класс оборудования и его устойчивую идентичность. Она не содержит конкретную модель нейросети и не описывает отдельный экземпляр устройства. + +### 5.2 CaptureProfile + +Текущий профиль записи: + +```text +xgrids-k1.viewer-live.fw-3.0.2.v1 +``` + +Он фиксирует значимые для совместимости свойства записанной камеры, media epoch, разрешение, calibration slot, media type и другие доказательства происхождения записи. + +### 5.3 Аттестация выбранной записи + +Сессия: + +```text +20260828T130511Z_viewer_live +``` + +Backend возвращает для неё: + +- equipment model identity; +- capture profile identity; +- attestation identity; +- состояние `attested-with-legacy-evidence`; +- неизменяемые identities исходного bundle и capability manifest. + +Старые записи не признаются совместимыми только по имени. Legacy-миграция использует проверяемые доказательства и закрывается отказом при неоднозначности. + +--- + +## 6. Как теперь определяется совместимость + +Совместимость не задаётся frontend-флагом и не выводится только из строки `K1`. + +Backend сопоставляет требования профиля с аттестованной записью: + +- plugin identity; +- equipment/capture identities; +- необходимые модальности; +- camera source; +- semantic channel; +- media type и initialization identity; +- ширину и высоту кадра; +- calibration identity; +- число media epochs; +- возможность seek. + +Если хотя бы обязательное условие не подтверждено, профиль не допускается к запуску. UI показывает серверное решение и не может самостоятельно сделать несовместимую запись совместимой. + +При появлении нового оборудования пользователь не должен видеть K1-профили до появления явно зарегистрированного совместимого source contract. + +--- + +## 7. Backend — фактически реализованное состояние + +Backend сейчас выполняет следующие обязанности: + +- хранит и проецирует записанные сессии; +- добавляет к сессии EquipmentModel и CaptureProfile attestation; +- загружает каталог portable RunDefinition; +- получает capability-рекламу Worker; +- вычисляет совместимость записи и профиля; +- выполняет server-side preflight; +- создаёт immutable job; +- хранит durable очередь и claim lease; +- принимает renew/start/succeed/fail от Worker; +- принимает result package по проверяемому manifest; +- публикует portable result; +- умеет повторять публикацию без повторного запуска моделей; +- восстанавливает незавершённую публикацию reconciler-ом; +- отдаёт общий result view интерфейсу. + +Job сохраняет точные identities источника, профиля, executor release, model manifest и resource profile. Поэтому задача не может незаметно переключиться на другой образ или конфиг после постановки в очередь. + +--- + +## 8. Frontend — фактически реализованное состояние + +Исторический UI до исправления0.36: + +- показывает список записей; +- показывает оборудование выбранной записи; +- показывает профиль записи; +- получает список portable профилей с backend; +- отображает совместимость и готовность Worker; +- запускает server-side preflight; +- создаёт job через пользовательскую кнопку `Рассчитать`; +- показывает ожидание, постановку в очередь, выполнение и ошибку; +- различает ошибку вычисления и ошибку публикации; +- позволяет повторить только публикацию, когда вычисления уже завершены; +- показывает связанные результаты; +- открывает общий визуальный разбор результата. + +Финальный live job `observatory-run-ce7051ca3d1a4734aea9e3d2c34b0851` создан именно через UI, а не прямым ручным HTTP-запросом. + +Уточнение2026-09-03: актуальный UI описан в0.36. Completion-плашки удалены, +архивные entries не предлагаются для расчёта; внизу показаны все загруженные +результаты. Реальные счётчики ещё предстоит добавить вместо одного индикатора +ожидания. Этот исторический job не является приёмкой нового recorded-first цикла. + +--- + +## 9. Worker 006 — фактически реализованное состояние + +На Worker одновременно существуют два независимых агента: + +```text +ndc-observatory-installed-lab-worker-agent +ndc-observatory-m49-worker-agent +``` + +Первый является новым generic installed-package агентом LAB V1. Второй сохраняет доказанный M4.9-контур до отдельной миграции. + +Это переходное сосуществование агентов, не доказательство эксклюзивной GPU-нагрузки и не два разрешённых параллельных AI-профиля. + +При последующем read-only аудите 1 сентября подтверждены оба агента, отдельные legacy perception/Triton containers и точные installed manifests. Также обнаружены работающие `sentinel-frigate` и `sentinel-ollama` с доступом к GPU; моментальный общий VRAM usage составлял 9256 MiB. Это не доказывает одновременный inference этих сервисов, но перед benchmark нового профиля необходимо обеспечить отдельное согласованное GPU-окно. Аудит ничего не запускал и не останавливал; остановка сервисов другого продукта не подразумевается этим документом. + +Generic агент: + +- читает точные registries только для чтения; +- рекламирует установленный package backend; +- забирает только совместимые задания; +- проверяет все job identities; +- материализует источник; +- запускает каждый component в отдельном контейнере; +- исполняет стадии последовательно; +- проверяет выход каждой стадии; +- собирает result package; +- передаёт его backend; +- завершает job только после подтверждённой публикации. + +--- + +## 10. Границы существующих LAB V1 Docker-контейнеров + +Каждая стадия существующего LAB V1 запускается отдельно. Между стадиями передаются проверяемые файлы, а не неявное состояние процесса. Это описание установленного batch package; новый standalone streaming профиль имеет границу, определённую в разделе 0.2. Изоляция сохраняется, но файловые whole-session barriers не переносятся как требование нового runtime. + +Общие ограничения component containers: + +- сеть `none`; +- root filesystem только для чтения; +- все Linux capabilities сняты; +- `no-new-privileges` включён; +- входы подключены только для чтения; +- запись разрешена только в выход стадии и ограниченные tmpfs; +- GPU выдаётся только модельным стадиям; +- CPU и память ограничены resource profile; +- image выбирается по точному digest. + +Проверка EoMT-контейнера во время остановленного запуска подтвердила: + +```text +image: adba3dc8c97b161ba261ec44fca9ebe1680f117d1bcb1481440172cc3331a174 +network: none +readonly root: true +capabilities: ALL dropped +no-new-privileges: true +GPU count: 1 +memory limit: 24 GiB +CPU limit: 8 +``` + +Подготовительная стадия также была выполнена в отдельном изолированном контейнере без сети и без GPU. + +--- + +## 11. Точная установленная версия LAB V1 + +```text +package sha256: +1bc84be07634ff69ac7459a2c39dc8fc9bcee33f72985dfa2c6088bb78976d8e + +run definition sha256: +269d71a24b4e63cff54e01273f9d4b35fc6cdd72bc6fadec206169ae0777e6ac + +executor release sha256: +667858623962cd6d9849a8985b803f59e429916b5c56f76a6fc6c80c0c54526b + +generic agent image sha256: +5ad7d95baac63af13812cb693d492add4e806a333aba8e60edb2ea1aba754373 + +EoMT image sha256: +adba3dc8c97b161ba261ec44fca9ebe1680f117d1bcb1481440172cc3331a174 + +DDRNet image sha256: +e6c986100613ec804f0e0076ca8695abf43ff88ef9d5d85f6857e0b41db74051 +``` + +Offline validation: + +- backend contact: отсутствовал; +- claim: не выполнялся; +- package registries: прошли проверку; +- все три image identities: подтверждены; +- model/static assets: подтверждены; +- runtime paths: подтверждены; +- итог: ready. + +Activation: + +```text +activation identity: +9754709382e6479dd0d86666911ee6e03b39500732caa5eb422bd982c0669a5e +``` + +Rollback предыдущей установленной версии сохранён и доступен. + +--- + +## 12. Найденная полная ошибка и её исправление + +Предыдущий настоящий прогон: + +```text +observatory-run-b88245ae05d543048dfb8f61ca17ee03 +``` + +доказал, что первая модель EoMT полностью обработала 6 830 кадров. Ошибка появилась уже при переходе к DDRNet. + +Причина была не в модели и не в записи. DDRNet adapter перед запуском копировал все декодированные кадры EoMT во временную файловую систему контейнера размером 4 GiB. Малые тестовые записи помещались, поэтому дефект не проявлялся. Полная запись K1 не помещалась. + +Исправление: + +- ненужное полное копирование удалено; +- каждый входной файл предварительно проверяется; +- проверяется отсутствие подмены через symlink; +- проверяются descriptor, inode, размер и hash; +- после проверки DDRNet читает исходное дерево EoMT напрямую через read-only mount; +- временная файловая система больше не используется как копия всей записи. + +Добавлен отдельный regression test, который требует именно read-only путь EoMT и запрещает возврат к временному snapshot всей записи. + +### 12.1 Более важная ошибка: потеря realtime semantics + +Исправление tmpfs было корректным, но следующий live run обнаружил более фундаментальную проблему. + +Текущий package делает следующее: + +1. Полностью материализует запись. +2. Проверяет тысячи отдельных файлов до первого результата. +3. Собирает полное видео. +4. Декодирует все 6 830 кадров в PNG. +5. Запускает EoMT по всем 6 830 кадрам. +6. Только после полного завершения EoMT должен запускать DDRNet по всей записи. +7. Затем отдельно собирает видео, архивы и отчёты. + +Это воспроизводимый offline exporter, но не псевдо-реал-тайм контур. + +Факты остановленного запуска: + +```text +длительность исходной записи: 808.779495667 s, примерно 13 min 29 s +кадров: 6 830 +средний source rate записи: примерно 8.445 fps +время от создания job до остановки: примерно 32 min 54 s +первый EoMT output появился только после полной подготовки и декодирования +наблюдавшийся EoMT throughput: примерно 1.5-2 fps +подтверждённый промежуточный счётчик: не менее 283 masks +DDRNet: не достигнут +publication: не достигнута +``` + +Даже steady EoMT работал в несколько раз медленнее среднего темпа этой записи, а до первого результата прошла подготовка длиннее самой допустимой warm-up фазы. Последовательный whole-session barrier дополнительно откладывал DDRNet до полного завершения EoMT. + +Поэтому успешное завершение такого job через час не являлось бы acceptance. Оно лишь доказало бы offline batch correctness. + +### 12.2 Что именно нужно переделать + +Нужно сохранить полезные общие admission/queue/identity/publication механизмы и создать отдельный полный runtime, а не только ускорить две стадии LAB V1: + +- один общий observation contract для camera/cloud/pose, используемый live K1 и recorded replay; +- replay выдаёт наблюдения по исходным timestamps и с `speed=1.0`; +- модели заранее загружены и прогреты до начала измеряемой части; +- bounded queues вместо полного каталога decoded PNG; +- frame/chunk pipeline вместо барьера «вся запись через одну модель»; +- RF-DETR и DDRNet получают явные cadence/deadlines одного полного профиля; GPU inference сериализован общим scheduler; +- EoMT сохраняется отдельно и в первом DDRNet-профиле не запускается; +- LiDAR geometry, ranges, static-obstacle слой, temporal/motion и TGS вычисляются online из текущих данных; +- fusion/policy-shadow использует текущие outputs, а не только показывает независимые архивные слои; +- в сельском прототипе `hard_surface` допустим без road/sidewalk/bikeway различения; geometry occupied и unknown имеют приоритет; +- пропуски, deadline misses, output age и queue pressure измеряются как первые классы результата; +- визуальные артефакты формируются асинхронно и не тормозят inference path; +- полная запись не копируется и не декодируется заранее целиком; +- end-to-end wall time для `speed=1.0` не превышает длительность источника более чем на утверждённый допуск; +- полный профиль не рекламируется real-time qualified без performance receipt именно его полного состава. + +### 12.3 Новый обязательный performance receipt + +Offline validation images и digests остаётся необходимой, но недостаточной. + +Для real-time квалификации профиля нужен отдельный performance receipt, который содержит: + +- image/model/runtime identities, hardware и effective mission/equipment configuration; +- полный список обязательных слоёв и подтверждение их вычисления текущим запуском; + +- source duration и source cadence; +- warm-up duration; +- time to first output; +- effective timeline fps; +- effective inference fps для каждой модели; +- latency p50/p95/p99; +- output age p95/p99; +- deadline miss count; +- drop count и причины; +- maximum queue depth; +- GPU/CPU/memory envelope; +- wall-over-ideal ratio; +- pass/fail относительно RunDefinition performance contract. + +Без такого receipt нельзя объявлять профиль real-time qualified. Установленность, доступность/занятость Worker и квалификация — разные состояния. Явный ограниченный qualification/canary запуск экспериментального профиля допустим для получения evidence; это не обычный подтверждённый live-режим и не разрешение управления моторами. + +--- + +## 13. Горизонтальные проверки + +Горизонтальные проверки отвечают на вопрос: одинаково ли работают общие правила на разных частях системы. + +Проверяются: + +- одинаковая EquipmentModel/CaptureProfile логика в session API и setup compatibility; +- единые identities между checked-in definitions, package registry и Worker advertisement; +- одинаковая job identity в backend, агенте и component labels; +- одинаковая authority `observation-only` во всех слоях; +- одинаковые правила publication retry в backend и UI; +- отсутствие специальных новых LAB-страниц; +- независимость M4.9 и LAB V1 агентов; +- невозможность совместить профиль с неподходящим источником только на frontend. + +Целевые backend/Worker проверки последней сборки перед live run: + +```text +59 passed +Ruff passed +``` + +Эти проверки подтверждают identities, безопасность и функциональные контракты. Они не проверяли realtime throughput и поэтому не являются доказательством готовности LAB V1. + +Полный последовательный suite и frontend build после остановки не запускались: пользователь остановил текущий проход и потребовал сначала исправить саму архитектурную оценку. Следующий тестовый план должен начинаться с короткого realtime canary, а не с ещё одного полного часового batch. + +--- + +## 14. Историческая вертикальная проверка LAB V1 через интерфейс + +Остановленная вертикальная проверка шла по настоящему пользовательскому пути существующего batch package: + +```text +Observatory UI + -> выбор записи RAVNOVES004TREE + -> выбор LAB V1 + -> кнопка Рассчитать + -> server-side preflight + -> durable job + -> generic Worker claim + -> source materialization + -> prepare + -> EoMT + -> DDRNet + -> assemble + -> upload + -> publication + -> обновление UI + -> общий result viewer +``` + +Фактически подтверждено: + +- UI показал запись и LAB V1; +- кнопка `Рассчитать` была доступна; +- клик создал новый job; +- job сохранил точный current definition и executor release; +- generic агент забрал job; +- все 6 838 исходных файлов материализованы; +- prepare завершился; +- EoMT запущен в точном изолированном image; +- lease регулярно продлевается; +- аппаратный decode получил ровно 6 830 кадров; +- EoMT начал выдавать semantic masks; +- до остановки наблюдалось не менее 283 masks; +- производительность не соответствовала realtime назначению; +- пользователь потребовал немедленно остановить неверный batch acceptance; +- EoMT container получил штатный SIGTERM и был удалён; +- job завершился как failed с exit status 143; +- после обновления UI показывает именно эту новую ошибку EoMT/status 143; +- DDRNet, assemble, upload, publication и viewer не достигнуты; +- частичные артефакты runner очистил; +- generic agent, M4.9 agent и backend остались запущены. + +Финальное состояние текущего запуска: + +```text +state: failed +reason: explicit operator stop after performance contract violation +terminal code: executor-error +component: eomt +exit status: 143 (SIGTERM) +published result: none +``` + +Это не model correctness failure и не инфраструктурный crash. Это осознанный отрицательный acceptance result: текущая форма исполнения слишком медленная и архитектурно не соответствует псевдо-реал-тайму. + +--- + +## 15. Acceptance matrix существующего контура и нового scope + +Столбец `Live proof` ниже означает фактически выполненный Worker job на записи, а не physical-live. Готовность отдельных инфраструктурных механизмов не означает готовность нового полного профиля. + +| Возможность | Код | Конфигурация | Live proof | Текущий итог | +|---|---:|---:|---:|---| +| Durable общая очередь | да | active | M4.9 + LAB V1 claim | готово | +| EquipmentModel registry | да | K1 registered | K1 session projected | готово для K1 | +| CaptureProfile registry | да | K1 profile registered | session attested | готово для K1 | +| Backend compatibility | да | active | LAB V1 pass | готово | +| Frontend filtering/status | да | active | UI launch | готово | +| Generic installed package registry | да | active | exact advertisement | готово | +| LAB V1 install/activation | да | active | Worker ready | готово | +| Hardened component runner | да | active | prepare + EoMT inspected | готово | +| Replay speed 1.0 / streaming semantics | нет в package | потеряно | live run отрицательный | **P0 blocked** | +| Multirate model schedule | есть в старых profiles | не перенесён | нет | **P0 blocked** | +| Bounded frame queues без full predecode | частично в старом runtime | отсутствует в package | нет | **P0 blocked** | +| Realtime performance receipt | нет | нет | нет | **P0 blocked** | +| LAB V1 EoMT full input | batch-код есть | active | стартовал, остановлен | не принят по performance | +| LAB V1 DDRNet full input | batch-код есть | active | не достигнут | не доказано | +| Portable publication | да | active | M4.9 live | LAB V1 не достигнуто | +| Общий result viewer | да | active | M4.9 live | LAB V1 не достигнуто | +| Automatic publication reconciliation | да | active | tests | реализовано | +| M4.9 на generic package agent | частично | нет cutover | legacy agent live | остаётся | +| Второе реальное оборудование | контракты частично общие, реализация пока K1 | нет device/profile | нет | вне первого прототипа | +| Полное удаление legacy LAB-путей | частично | переходный режим | нет | остаётся | +| Полный standalone DDRNet + RF-DETR + LiDAR + TGS | reusable компоненты есть | TARGET утверждён | нет нового запуска | **не собран / не квалифицирован** | +| Общий static-obstacle слой без точных имён | vocabulary/визуальный слой существуют | reuse утверждён | сохранённый RAV004 — regression reference | проверить новый online путь | +| Coarse hard_surface для сельского прототипа | mapper/policy существуют | компромисс утверждён владельцем | нет нового полного запуска | не требует дополнительного segmenter | +| Online fusion/policy всех слоёв текущего run | отдельные части есть | новый контракт требуется | старый viewer и timing join не доказывают | **не завершено** | +| GPU exclusivity всего Worker | очередь не охватывает все сервисы | другие GPU-capable сервисы работают | read-only audit | отдельное согласованное окно до benchmark | + +--- + +## 16. Историческая оценка готовности — не процент нового профиля + +Ниже сохранена оценка предыдущего closeout для прослеживаемости. Она относилась к старому объёму Docker-LAB и не переносится на новый полный Perception-профиль. В новом scope готовность фиксируется четырьмя этапами и evidence, без придуманного общего процента. + +После отрицательного live acceptance прежнюю предварительную оценку `88%` использовать нельзя. Она переоценивала инфраструктурную готовность и не выделяла realtime semantics как самостоятельную крупную часть продукта. + +Предыдущая оценка была разделена: + +```text +инфраструктура записей / registry / queue / package / UI: примерно 85% +готовность основного лабораторного продукта с realtime acceptance: примерно 60% +``` + +Числа **85% / 60% не являются актуальной оценкой нового standalone профиля**. Его образ и полная квалификация пока отсутствуют; local/read-only архитектурный аудит выполнен, этап 1 завершён частично. + +Историческая весовая логика той оценки: + +| Блок | Вес | Выполнено | +|---|---:|---:| +| Записи, EquipmentModel, CaptureProfile, compatibility | 20% | 20% | +| Durable queue, immutable jobs, publication foundation | 15% | 15% | +| Generic package build/install/hardening | 15% | 15% | +| Общий UI выбора и запуска | 10% | 10% | +| Псевдо-реал-тайм FrameSource и multirate scheduler | 20% | 0% в новом package | +| LAB V1 realtime performance proof и publication | 10% | 0% | +| M4.9 generic migration | 4% | 0% | +| Второе реальное оборудование | 3% | 0% | +| Controlled retirement legacy | 3% | 0% | + +Сохраняется принцип, но не процент: ценность Observatory — повторяемое полное исполнение в согласованном real-time envelope и видимые ошибки, а не просто завершившийся контейнер. + +--- + +## 17. Исполнение — четыре актуальных этапа, обновлено 2026-09-03 + +Единственный подробный маршрут: [ExecPlan](/Users/dcconstructions/Downloads/mnt/NODEDC/NODEDC_MISSION_CORE_m5_observatory/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md). +Основной сценарий: **запись → нерассчитанный профиль → Рассчитать → фактический +прогресс → опубликованный результат → повторный сохранённый просмотр**. +После лабораторного отбора тот же профиль готовится к работе на борту. +Длительный расчёт допустим; сетевой realtime PASS не является входным билетом. + +### Этап 1. Основа и идентичность — реализована, локально проверена + +Очередь/claim, защита от дубликатов, совместимость, точный cache и селектор +готовы. Не повторяем этот ремонт. Evidence: 720 frontend tests и 52 queue/API tests, +build/typecheck и browser QA из 0.36. Новую версию нельзя спрятать старым LAB-именем. +Завершение видно по нижнему результату, не по completion-кнопке/плашке. + +Это граница инженерного результата этапа 1. Новый run и его публикация проверены +в0.38; полная сквозная визуальная приёмка остаётся в этапе2. + +### Этап 2. Полноценная лаборатория на записях — следующий активный этап + +Progress-часть2A реализована и активирована (0.38). M49 ×004TREE рассчитан, +опубликован и открывается общим camera/TGS replay с Core после перезапуска (0.39). +Общий source-cache и проверка LiDAR pack до decode установлены на Worker (0.43): +готовые входы переиспользуются; cold whole-input barrier пока сохранён. +Остаток2A и полная визуальная приёмка2B, включая сохранение ручного ракурса, +ещё не приняты. + +- **2A — режим полного анализа и прогресс.** Версионированный recorded-analysis: + исходный clock/причинность, учёт всех обязательных inputs/outputs по расписанию + профиля, bounded backpressure вместо потерь ради 1×. Инкрементальная подача, + без обязательной полной предварительной передачи исходной записи. + Реальные Worker-счётчики → backend → UI, без выдуманных процентов/ETA. + Preparation/warmup/compute/transport/publication измеряются раздельно. +- **2B — первый полный проход M4.9T5 × RAVNOVES004TREE.** UI → Worker → sealed + package → публикация → маркер профиля внизу → общий просмотр. Проверить + полноту TGS/timeline, исчезновение рассчитанной версии из выбора и повторное + открытие без job/inference. Архивный результат без binding не заменяет proof. +- **2C — LAB V1 и другая запись.** LAB V1 × 004TREE, затем оба профиля × RAVNOVES00, + строго последовательно. EoMT допускается считать медленно; не менять скрыто + модели/stride/разрешение ради PASS. RAVNOVES01 пока негативный compatibility case. + Попытка0.45 потеряла lease на EoMT, не опубликована. Heartbeat исправлен; + перед повтором нужна новая sealed disk policy вместо350GiB floor и ранний + preflight. Не считать тесты/неудачный canary успешной матрицей. +- **2D — повторное использование, восстановление, каталог.** Перезапуск, + краткий обрыв, compute failure, повтор только публикации, повреждённые/ + недоступные artifacts, отсутствие дубликатов. Постраничный каталог и поиск + источников реализованы и проверены (0.44); Legacy исключён из Обсерватории + без удаления истории. Оставшиеся recovery cases ещё открыты. + В0.45 исправлены outbox starvation и краткая потеря heartbeat/ACK; установлены + на Core/Worker. Long-outage и полный visual cycle пока не приняты. + +**Готовность:** два текущих профиля на двух совместимых записях, полный +предусмотренный анализ, настоящий прогресс, опубликованный просматриваемый +результат и сохранённый просмотр после перезапуска без нового compute. +Все текущие профили рассчитаны → выбор пуст, «Рассчитать» нет, «Обновить» есть. +Один удачный M4.9 run **с принятым visual replay** закрывает2B, не весь этап2. + +### Этап 3. Самостоятельные Docker-профили и эксперименты + +На уже сделанном runtime собрать полный **DDRNet + RF-DETR + LiDAR/distance + +static obstacles + temporal/motion + TGS/costmap + policy-shadow**. Весь состав +реально рассчитывается одним профилем без чужих сохранённых overlays. +Веса/runtime/config в переносимой поставке; cold start без developer checkout/ +скрытого model cache. Записи/результаты/секреты внешние, backend/БД вне образа. + +Понятные `ndc-` profile/image имена, версии и digests. Один Worker 4090 — один +активный профиль. DDRNet основной, EoMT отдельная сохраняемая альтернатива. +Сельский hard_surface и общий static-obstacle достаточны; качество людей, +животных, динамики и расстояний проверяется отдельно, не выводится из FPS. + +**Готовность:** standalone/cold-start proof и сравнимая матрица конфигураций на +нескольких маршрутах: качество, full-graph compute, ресурсы, транспорт, +подготовка/прогрев/публикация раздельно. Перегрузка допускается как честный +эксперимент, не отменяя limits памяти/очередей. Worker-only baseline — не +гарантированный FPS будущего борта; не вычитать несвязанные p95 и не мерить модель viewer FPS. + +### Этап 4. Отбор кандидата и фактический борт + +Это будущая стадия. На текущем шаге на борт ничего не переносится. + +Зафиксировать удачный image/config, совместимое железо/калибровки и evidence. +После появления компьютера — проверить этот граф и контракты на местном входе, +измерить реальные latency/ресурсы/качество/recovery. Иная архитектура, например +Apple Silicon вместо CUDA, требует подходящей сборки и повторной квалификации. + +**Готовность сейчас:** пакет кандидата; реальный перенос pending до оборудования. +Контроллер/ArduRover, watchdog, stop/slow, моторы и автономный маршрут — отдельный +допуск, не скрытая часть Observatory. Отсутствие борта не блокирует этапы 1–3. + +**Непосредственно дальше:** новая sealed disk policy и ранний preflight LAB V1, +сохранение диагностики до cleanup, затем успешная матрица2C. Также остаток2A — +versioned incremental cold input и полный +анализ; warm reuse уже установлен (0.43). Завершить visual acceptance camera/TGS replay из0.39/0.42: +native camera-state preservation и подробная оценка покрытия/качества. +Не повторять упаковку/compute вместо устранения ограничения blueprint activation. +Затем последовательная матрица профилей/записей2C и recovery/каталог2D. +Memory lifecycle остаётся критерием приёмки, но отдельный browser gate не +блокирует input/catalog/contracts. Не повторять старый ремонт claim/Docker VM/ +селектора, не запускать сетевой canary вместо полного лабораторного цикла. + +--- + +## 18. Что не входит в первый прототип и текущую правку документов + +- развёртывание на Synology; +- использование 21-го deployment canon; +- создание нового LAB-микроприложения; +- добавление вымышленного второго оборудования без реальной записи; +- признание лабораторных результатов пригодными для навигации или safety; +- изменение отдельного M49-контейнера во время LAB V1 cutover. + +Дополнительно вне первого прототипа: + +- городской автопилот и разделение дороги/тротуара/велодорожки; +- распознавание точных видов static-предметов вместо существующего obstacle-класса; +- дополнительный segmenter, обязательная новая разметка или обучение; +- доработка EoMT как предварительное условие DDRNet-профиля; +- новое оборудование, двадцать готовых профилей, полный mission configurator и управление моторами; +- самостоятельная остановка сторонних GPU-сервисов без отдельного согласования. + +Архитектурный выбор уже ограничен: один активный полный профиль, RF-DETR + DDRNet внутри него и сериализованный GPU inference первого прототипа. Конкретные cadence/buffers подтверждаются измерением. Одновременный inference EoMT и DDRNet и конкурирующие профили не допускаются; существующий сравнительный LAB V1 исполняет эти модели последовательно. Разные внутренние environments не оправдывают whole-session barriers и не требуют отдельных установленных LAB-приложений. + +Проект и проверка выполняются локально относительно Mission Core и Worker 006. Никакой Synology deployment scope в этот closeout не входит. + +--- + +## 19. Граница безопасности результата + +Существующие лабораторные профили и новый прототип остаются observation-only / policy-shadow. + +Их результаты: + +- можно просматривать; +- можно сравнивать; +- можно использовать для исследовательской квалификации; +- нельзя автоматически принимать как команды; +- нельзя использовать как доказанную safety-функцию; +- нельзя использовать для управления аппаратом без отдельного acceptance процесса. + +Эта граница проходит через backend contract, job, Worker labels, component containers и result view. + +--- + +## 20. Главный итог + +Mission Core имеет рабочую основу записей, equipment/capture admission, очереди и публикации; многие нужные алгоритмы уже существуют. Но текущие portable packages не исполняют полный состав, видимый в сохранённой лаборатории. M4.9 portable — CPU TGS; LAB V1 — медленная последовательная сегментация EoMT→DDRNet. Новый полный самостоятельный Docker пока отсутствует. + +Утверждён первый сельский Perception-профиль: **DDRNet + RF-DETR + LiDAR-расстояния/static-объекты + TGS/costmap + temporal/motion + policy-shadow**. Используем существующий obstacle-класс и допускаем coarse hard_surface, не решая городскую fine-grained задачу. EoMT сохраняем отдельно. Один Worker обслуживает один полный профиль; записи и будущий live используют один runtime. + +Актуальный маршрут — четыре этапа 17, сводка0.45. Основа этапа 1 уже реализована +и локально проверена: queue/claim, exact cache, version binding и селектор. +Полный потоковый граф тоже существует как инженерный прототип; это не +готовый standalone продукт и не повод писать его заново. + +Этап 2 выполняется: настоящие счётчики активированы, M49 ×004TREE рассчитан и +опубликован, exact cache/документ проверены после исправления reindex и рестарта. +Общий source-cache и ранняя проверка LiDAR pack установлены в оба агента Worker +(0.43); повторная передача готовых входов и raw decode на cache hit устранены. +Каталоговая часть2D реализована: typed Legacy separation и cursor pages (0.44). +Saved semantic adapter, outbox и transient heartbeat recovery установлены (0.45). +Реальный LAB V1 ×004TREE не опубликован; перед повтором исправляется sealed +disk policy350GiB и ранний admission, не модельное качество и не VRAM. +Portable camera/TGS-viewer работает с кэшем Core (0.39), но ручной ракурс при смене +слоя ещё сбрасывается. Полный recorded-analysis и визуальная приёмка открыты; +затем LAB V1/вторая запись и оставшиеся recovery cases. Не подменять визуальную +приёмку JSON, unit tests или старым succeeded/not-required. +После этого этап 3 — самостоятельный полный +профиль и сравнение конфигураций, этап 4 — отбор и фактический борт. + +Сетевой realtime PASS не блокирует лаборатории. Исторические FPS/latency/canary +сохраняют исходные FAIL; физическое управление не выполнялось. Итерация0.38 +обновила локальный8000 и Worker control layer;0.39 изменила только Core/replay. +Фактического переноса на борт нет. + +```text +Один самостоятельный образ = полный Perception-профиль; +один Worker = один активный профиль; +recorded-analysis и realtime-rehearsal = разные режимы одного переиспользуемого runtime; +сколько угодно совместимых записей = отдельные воспроизводимые испытания; +static-obstacle и coarse hard_surface достаточны для первого сельского прототипа; +успешный replay/FPS не равен автоматическому допуску автономии или моторов. +``` + +--- + +## 21. Актуализация: модульный AI-слой Обсерватории — 2026-09-03 + +Этот раздел заменяет старые утверждения выше о едином самостоятельном +Perception-образе и фиксированном профиле как актуальном направлении. Новый +локальный контур собирает конфигурацию из независимых модулей. Legacy-контур и +исторические LAB не изменялись; deployment canon 21 и Synology в эту работу не +входили. + +В Обсерватории удалены фиксированный selector профиля и действия «Обновить» / +«Рассчитать». Для выбранной записи всегда доступно действие +«Сконфигурировать AI-слой». Каноническое модальное окно содержит отдельные +группы «Сегментация», «Объекты», «Облако точек / TGS», «Дистанция», «Движение» +и «Политика», один Select на группу, крестик и кнопку «Рассчитать». Декоративные +обводки, разделительные линии и modal rim удалены; группы разделяются фоном, +отступами и типографикой. В узком viewport длинный статус переносится под +заголовок и не пересекает его. Каноническая клавиатурная индикация фокуса +сохранена. + +Фактическая модульная семантика: + +- DDRNet и EoMT — две независимые альтернативы сегментации; ни одна не зависит + от результата другой; +- RF-DETR — отдельный модуль рамок и классов `detections.2d`; +- object-distance — отдельный модуль дальности. Он явно использует результат + RF-DETR, синхронный LiDAR, pose и calibration; +- TRAVEL TGS — отдельный алгоритмический модуль облака точек, ground/costmap и + собственной causal history. Он не зависит от RF-DETR или сегментации; +- выбор object-distance автоматически добавляет RF-DETR как видимую + зависимость; TGS и object-distance можно выбрать вместе. Сервер создаёт для + них два независимых durable job, а Worker исполняет тяжёлые GPU-шаги + последовательно. + +Установленные NODE.DC module repositories: + +- `ndc/mission-core-ai-module-camera-source`; +- `ndc/mission-core-ai-module-ddrnet`; +- `ndc/mission-core-ai-module-eomt`; +- `ndc/mission-core-ai-module-rf-detr`; +- `ndc/mission-core-ai-module-object-distance`; +- `ndc/mission-core-ai-module-tgs`. + +Активный каталог Worker 006 содержит четыре новых sealed packages: +`ai-segmentation-ddrnet-v1`, `ai-segmentation-eomt-v1`, +`ai-detection-rf-detr-v1`, `ai-range-object-distance-v1`. TGS продолжает +исполняться своим сохранённым M49 portable package, но участвует в новом +конфигураторе как независимый модуль. Точный активный directory release: +`20260903-v5`, release SHA-256 +`a87c82adfa1058f14f850f488ace38e5c7c9d9e2145d4678a81b52f2a1aad573`. +Agent image SHA-256: +`d6f2ef1a3f38ebc8503b62296ca9def10472a60a41ffc5edd123df565520dec8`. + +RF-DETR и object-distance используют один RF model manifest, но имеют разные +resource profile identities: standalone detector и составная +camera + detector + LiDAR задача не схлопываются в одну executor identity. +Сборщик релиза теперь отклоняет любые повторяющиеся executor identities до +установки. На Worker агент v5 запущен с restart count 0; старые LAB V1 и M49 +agents продолжают работать отдельно. + +Для `20260828T130511Z_viewer_live` DDRNet, EoMT, RF-DETR и object-distance +проходят source compatibility, executor, sealed definition и durable queue +preflight. Существующий опубликованный M49 TGS определяется как exact result. +RF-DETR и object-distance публикуют строгий +`missioncore.recorded-ai-layer-review/v1`; общий replay отображает 2D-рамки, +класс/confidence и измеренную дальность либо явное отсутствие дальности. + +Карточки AI-расчётов появляются в «Лабораторных доказательствах» сразу после +постановки в очередь и показывают конфигурацию, реальную фазу, прогресс и оценку +оставшегося времени. После публикации используются общие действия открыть, +переименовать и удалить. + +Граница фактического proof: registry, package seals, Worker startup, API +preflight, UI interaction, frontend/backend tests и production build проверены. +Новый полный 6830-frame RF-DETR/object-distance inference в рамках этой +установочной приёмки не запускался, поэтому качество и полная длительность этих +двух новых модулей ещё не являются измеренным результатом. + +Дополнительная продуктовая сверка 2026-09-03 закрыла повторные запуски. Одна +исходная запись, один module setup и одна версия RunDefinition образуют один +расчёт независимо от нового UI idempotency key и от последующего ремонта +каталожных digest записи. Модалка читает durable-историю до выбора: уже +рассчитанный или поставленный в очередь модуль отключён и помечен «Уже +рассчитано для этой записи» с требованием выбрать другую конфигурацию. Тот же +запрет повторно проверяется Core внутри транзакции; прямой повтор TGS возвращает +HTTP 409 и не увеличивает число job. + +Durable-журнал не удаляется, но завершённые служебные job больше не выдаются за +пользовательские лабораторные доказательства. В списке видна одна временная +карточка только пока расчёт или публикация действительно продолжаются; после +публикации остаётся одна обычная карточка результата с действиями открыть, +переименовать и удалить. Для `RAVNOVES004TREE` опубликованный TGS представлен +как открываемый `LAB M4.9T5`; два старых transport failure и прежний +`succeeded/not-required` остаются только audit history. + +Финальная визуальная правка убрала декоративные контуры с progress-карточек, +модульных блоков, модального окна и replay-поверхности, сохранив доступный +keyboard focus. Пояснение результата и элементы replay наследуют канонический +шрифт Mission Core; активная карточка явно пишет прогноз времени либо сообщает, +что прогноз появится после начала обработки. diff --git a/docs/handoff/ai-inference-source-documents/manifest.json b/docs/handoff/ai-inference-source-documents/manifest.json new file mode 100644 index 0000000..83aafbe --- /dev/null +++ b/docs/handoff/ai-inference-source-documents/manifest.json @@ -0,0 +1,16 @@ +{ + "archived_at": "2026-09-05", + "role": "historical_desktop_reports_not_current_instructions", + "files": [ + { + "filename": "_MISSING_CORE_MODULAR_AUDIT_AND_PLAN_2026-09-03.md", + "sha256": "d6c201d083fbec4b1db031379b515ff821a09ccfa0cea62443e211a9d76cb1c2", + "bytes": 53637 + }, + { + "filename": "_MISSING_CORE_OBSERVATORY_DOCKER_LABS_FINAL_STATUS_2026-09-01.md", + "sha256": "45e870700baddab8f31a2f0f0bfe1f9e99e8e73a490195c1e6a3beb5265e49ee", + "bytes": 330260 + } + ] +} diff --git a/src/k1link/observatory/setups.py b/src/k1link/observatory/setups.py index 0d2f381..6b75705 100644 --- a/src/k1link/observatory/setups.py +++ b/src/k1link/observatory/setups.py @@ -148,7 +148,7 @@ class LaboratorySetup: ] if compatible and ready_result_ids: action = "open-existing" - action_reason = "Точный запечатанный результат уже опубликован в Обсерватории." + action_reason = "Точный запечатанный результат уже опубликован в AI Inference." elif compatible and any( result.access == "legacy-lab" for result in self.preserved_results ): diff --git a/src/k1link/web/modular_observatory_api.py b/src/k1link/web/modular_observatory_api.py index f5f1ea5..acc81bf 100644 --- a/src/k1link/web/modular_observatory_api.py +++ b/src/k1link/web/modular_observatory_api.py @@ -174,7 +174,7 @@ def build_modular_observatory_router( try: source = store.get_session(request.source_session_id).summary except SessionNotFoundError as exc: - raise HTTPException(status_code=404, detail="Запись Обсерватории не найдена.") from exc + raise HTTPException(status_code=404, detail="Запись AI Inference не найдена.") from exc if source.lab is not None: raise HTTPException( status_code=409, @@ -412,7 +412,7 @@ def build_modular_observatory_router( try: display_name = composition_runs.rename_projection(run_id, request.display_name) except CompositionRunError as exc: - raise HTTPException(404, "Результат AI inference не найден.") from exc + raise HTTPException(404, "Результат AI Inference не найден.") from exc return { "schema_version": "missioncore.observatory-ai-composition-run-projection/v1", "run_id": run_id, @@ -429,7 +429,7 @@ def build_modular_observatory_router( try: composition_runs.delete_projection(run_id) except CompositionRunError as exc: - raise HTTPException(404, "Результат AI inference не найден.") from exc + raise HTTPException(404, "Результат AI Inference не найден.") from exc return Response(status_code=204) @router.get("/api/v1/observatory/ai-runs") diff --git a/src/k1link/web/observatory_api.py b/src/k1link/web/observatory_api.py index 009edcc..3d7f8a3 100644 --- a/src/k1link/web/observatory_api.py +++ b/src/k1link/web/observatory_api.py @@ -456,7 +456,7 @@ def build_observatory_router( if setup_registry is None: raise HTTPException( status_code=503, - detail="Каталог legacy-сетапов Обсерватории недоступен.", + detail="Каталог legacy-сетапов AI Inference недоступен.", ) source = source_summary(source_session_id) return setup_registry.catalog( @@ -623,7 +623,7 @@ def build_observatory_router( del source_session_id raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории не прошёл проверку целостности.", + detail="Каталог сетапов AI Inference не прошёл проверку целостности.", ) @router.post("/api/v1/observatory/run-preflights") @@ -633,7 +633,7 @@ def build_observatory_router( del request raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории не прошёл проверку целостности.", + detail="Каталог сетапов AI Inference не прошёл проверку целостности.", ) if setup_registry is not None and run_preparation_ledger is not None: @@ -688,7 +688,7 @@ def build_observatory_router( if not isinstance(setups, list): raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) projected = next( ( @@ -701,7 +701,7 @@ def build_observatory_router( if projected is None: raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) definition = projected.get("run_definition") if not isinstance(definition, dict): @@ -725,7 +725,7 @@ def build_observatory_router( ): raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) if compatibility.get("compatible") is not True: raise HTTPException( @@ -743,7 +743,7 @@ def build_observatory_router( ): raise HTTPException( status_code=503, - detail="Dispatch-контракт Обсерватории не установлен.", + detail="Dispatch-контракт AI Inference не установлен.", ) definition_id = definition.get("definition_id") definition_version = definition.get("version") @@ -759,7 +759,7 @@ def build_observatory_router( ): raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) try: intent = ObservatoryRunPreparationIntent( @@ -826,7 +826,7 @@ def build_observatory_router( del request raise HTTPException( status_code=503, - detail="Подготовка расчётов Обсерватории недоступна.", + detail="Подготовка расчётов AI Inference недоступна.", ) @router.get("/api/v1/observatory/run-preparations/{preparation_id}") @@ -840,7 +840,7 @@ def build_observatory_router( del preparation_id raise HTTPException( status_code=503, - detail="Подготовка расчётов Обсерватории недоступна.", + detail="Подготовка расчётов AI Inference недоступна.", ) if recorded_job_queue is not None and ( @@ -1022,7 +1022,7 @@ def build_observatory_router( if not isinstance(setups, list): raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) projected = next( ( @@ -1035,7 +1035,7 @@ def build_observatory_router( if projected is None: raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) compatibility = projected.get("compatibility") preflight = projected.get("preflight") @@ -1043,7 +1043,7 @@ def build_observatory_router( if not isinstance(compatibility, dict) or not isinstance(preflight, dict): raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) if compatibility.get("compatible") is not True: raise HTTPException( @@ -1064,7 +1064,7 @@ def build_observatory_router( if not isinstance(definition_sha256, str): raise HTTPException( status_code=503, - detail="Каталог сетапов Обсерватории нарушил контракт.", + detail="Каталог сетапов AI Inference нарушил контракт.", ) try: admission = recorded_binding_service.admit( @@ -1175,7 +1175,7 @@ def build_observatory_router( except ObservatoryRecordedQueueNotFoundError as exc: raise HTTPException( status_code=404, - detail="Расчёт Обсерватории не найден.", + detail="Расчёт AI Inference не найден.", ) from exc except (ObservatoryRecordedQueueError, ValueError) as exc: raise HTTPException( @@ -1206,7 +1206,7 @@ def build_observatory_router( except ObservatoryRecordedQueueNotFoundError as exc: raise HTTPException( status_code=404, - detail="Расчёт Обсерватории не найден.", + detail="Расчёт AI Inference не найден.", ) from exc except (ObservatoryRecordedQueueError, ValueError) as exc: raise HTTPException( @@ -1305,17 +1305,17 @@ def build_observatory_router( except SessionNotFoundError as exc: raise HTTPException( status_code=404, - detail="Проекция Обсерватории не найдена.", + detail="Проекция AI Inference не найдена.", ) from exc except SessionIntegrityError as exc: raise HTTPException( status_code=409, - detail="Запись не является управляемой проекцией Обсерватории.", + detail="Запись не является управляемой проекцией AI Inference.", ) from exc except ValueError as exc: raise HTTPException( status_code=422, - detail="Некорректные параметры проекции Обсерватории.", + detail="Некорректные параметры проекции AI Inference.", ) from exc return ObservatoryProjectionDocument( schema_version=OBSERVATORY_PROJECTION_SCHEMA, @@ -1333,17 +1333,17 @@ def build_observatory_router( except SessionNotFoundError as exc: raise HTTPException( status_code=404, - detail="Проекция Обсерватории не найдена.", + detail="Проекция AI Inference не найдена.", ) from exc except SessionIntegrityError as exc: raise HTTPException( status_code=409, - detail="Запись не является управляемой проекцией Обсерватории.", + detail="Запись не является управляемой проекцией AI Inference.", ) from exc except ValueError as exc: raise HTTPException( status_code=422, - detail="Некорректный идентификатор проекции Обсерватории.", + detail="Некорректный идентификатор проекции AI Inference.", ) from exc return Response(status_code=204)