From d264cbce04b7aeb7e77afb50de8efa7da4bb0bbd Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Wed, 2 Sep 2026 11:03:26 +0300 Subject: [PATCH] docs(perception): record stage-two scheduler and cell freshness proof --- .../OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md | 15 ++- .../0049-stream-first-perception-profiles.md | 39 ++++++- .../PERCEPTION_STREAM_STAGE1_2026-09-01.md | 110 ++++++++++++++++++ 3 files changed, 153 insertions(+), 11 deletions(-) diff --git a/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md b/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md index b01b1dc..b2ba1d0 100644 --- a/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md +++ b/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md @@ -1,8 +1,8 @@ # Observatory: четыре этапа создания полного real-time Perception-профиля -Дата: 2026-09-01; обновлено 2026-09-02 10:16 МСК. **Этап 1 закрыт как состав, контракты и технический baseline; GO на инженерную реализацию этапа 2. Real-time qualification НЕ выдана.** Цель прежняя: переносимые полные профили и снижение задержек всей цепочки. Финальный six-layer PyTorch pilot: 128/128 без drops, p95/p99 122.11/141.40 ms в auto clock mode. Полностью свежи 27/128 scenes: 52 source gaps, 49 stale costmaps. Пять сцен истекли между publisher guard и receipt и получили NO_GO. Этапы 2–4 ещё не выполнены; standalone/network/full-session/vehicle proof отсутствуют. Default остаётся PyTorch; TensorRT numeric/material parity не пройдена. +Дата: 2026-09-01; обновлено 2026-09-02 11:00 МСК. **Этап 1 закрыт как engineering baseline; этап 2 начат, выполнен первый инкремент — общие queue/scheduler и per-cell expiry. Real-time qualification НЕ выдана.** Два последовательных PyTorch-пилота: по 128/128 без drops. Per-cell вариант: p95/p99 123.91/136.17 ms, 76 свежих six-layer результатов из 76 доступных sensor pairs; 52 missing pairs остаются NO_GO. Просроченные ячейки отдельно блокируются, а не объявляются свежими. Standalone/network/full-session/vehicle proof отсутствуют; этапы 3–4 не начаты. Default PyTorch, TensorRT numeric/material parity не пройдена. -Последнее изменение: `097e450` вводит общий six-layer freshness ABI, dependency-age propagation, payload validation и повторную оценку у consumer; все 128 модельных/геометрических/motion/TGS/material результатов точны к прежнему PyTorch-reference. Условия Worker закреплены в read-only readiness evaluator и candidate manifest; evaluator не приобретает lease и не управляет частотами. Предыдущий fixed-clock A/B (p99 PyTorch 77.02 ms) остаётся отдельным evidence, не переносится на auto-mode или новую полную квалификацию. Текущий шаг не менял clocks/quotas/weights/thresholds. Следующий шаг — общий lifecycle/data plane, per-cell expiry и standalone package этапа 2; не новая модель и не автономия. +Последние изменения: `bcacb02` — общий bounded scheduler с корректным cancel/release; `1f8101e` — per-cell timestamps/expiry, повторная проверка и хеширование derived consumer view. Сырые model/geometry/motion/TGS/material outputs точны к reference на всех 128 кадрах в обоих runs. Mandatory layer guard не ослаблен. Старый whole-scene контроль дал 25 свежих результатов, новый per-cell — 76; это изменение адресности блокировки, не рост perceptual accuracy. Clock auto менялся самостоятельно: разница задержек не приписывается оптимизации. Следующий шаг этапа 2 — supervisor/StreamStart fencing и authoritative GPU ownership, затем binary ingress и standalone package. Условия Worker проверяет read-only evaluator; он пока не приобретает lease. Clocks/quotas/weights/thresholds не менялись; прежний fixed-clock PASS не переносится на новый runtime. Текущий evidence: [отчёт этапа 1](../experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md), [ADR 0049](adr/0049-stream-first-perception-profiles.md), [candidate manifest](../config/perception/k1-perception-ddrnet39-rfdetr-tgs-prototype-v1.json). Запрет full-source preload закреплён в новом контракте; старый batch materializer пока не удалён и продуктовый путь не переключён. @@ -143,6 +143,8 @@ IPC/сети, копирований и оркестрации. Вычислит ## Этап 2 — Самостоятельный Docker с полным потоковым вычислением +**Текущий статус, 11:00 МСК:** в работе. Общие mailbox/serial GPU stage подключены к полному пилоту; per-cell expiry проверен двумя Worker-прогонами. Это первый инкремент, не завершённый supervisor/lease/data plane и не самостоятельный image. GO на этап 3 пока нет. + **Цель:** один самостоятельный контейнер принимает поток и реально рассчитывает DDRNet, детекции, расстояния, motion, TGS/costmap и policy-shadow; ничего не дорисовывается из старых LAB. **Вход:** контракты и baseline этапа 1. @@ -249,8 +251,11 @@ EoMT — семейство ViT-моделей сегментации изобр - 2026-09-02 09:11–09:40 МСК: численная диагностика frame 115 связала большую часть mismatch с TF32, а critical policy flip — с sigmoid ties и ничьей двух ground votes. `c6c42c2` переводит tie в unknown/NO_GO; 210 cell×frame значений на 41 кадре изменились только консервативно. 122 focused tests PASS. Masks/detector/geometry/motion outputs не изменились от этой правки. - 2026-09-02 09:31–09:37 МСК: по явному разрешению владельца A/B stock clock lock (requested SM 2610 / memory 10501 MHz; observed CUDA 2610/10251) без изменения 450 W или Docker limits. Auto B: p95/p99 123.14/138.16 ms; locked C/D: 64.08/70.46 и 63.97/67.77 ms; pinned PyTorch E: 71.80/77.02 ms; auto-restored F: 116.71/144.88 ms. Все шесть новых полных проб 128/128, 0 drops; функциональная parity clock A/B 128/128. Это повторяемый bounded latency PASS при указанном envelope, не whole-product qualification. Evidence: `.runtime/perception-parity-pacing-worker-20260902T0911MSK/manifest.json`, SHA-256 `eac303c218ab391ed5dc2cd8d94be6f1eeecec2effc123da7585135a8b63f2dd`. - 2026-09-02 09:40 МСК: clock resets успешны, GPU снова auto/P8 210/405 MHz, power limit 450 W; pilot containers=0. Четыре Mission Core сервиса восстановлены в прежнюю конфигурацию, Triton healthy/ready=200; прежние сторонние restart-loop дефекты не исправлялись. Ollama/Frigate exited/restart=no, Mac 8000=200, 8765 закрыт. Raw/weights не в Git, push/deployment не выполнялись. -- Этап 1: частично выполнен. Следующие задачи: закрепить воспроизводимый operating envelope Worker и выходной layered-freshness ABI, продолжить общий runtime. Reference PyTorch остаётся допустимой исходной точкой; TensorRT numeric/material parity требуется до его продвижения, но не блокирует reference-ветку. Затем application↔Worker streaming transport и длинные/разные записи. Нельзя расширять короткий latency PASS до сети/автономии или подменять unavailable sensor evidence свежими данными. -- Этапы 2, 3, 4: не начаты. Продуктовый backend/frontend path, active registry, canonical local 8000 и физический источник не переключались. Старый full-source materializer остаётся legacy; новый streaming transport ещё не реализован. +- 2026-09-02 10:16 МСК: этап 1 закрыт как engineering baseline (`097e450`, `adcca7a`), не qualification. Six-layer ABI и Worker envelope закреплены; final auto C: 128/128, 0 drops, p95/p99 122.11/141.40 ms, 27 fresh scenes. Подробности и известный historical baseline test FAIL сохранены в отчёте. +- 2026-09-02 11:00 МСК: этап 2 начат. `bcacb02` переносит queue/GPU scheduler в common perception, ограничивает drop-history и проверяет владение входом при release/cancel. `1f8101e` добавляет адресную свежесть costmap; core tests и полный GPU-пилот используют тот же код. 202 focused tests, Ruff, mypy четырёх изменённых core modules и diff-check PASS. +- Два последовательных Worker runs: whole-scene p95/p99 125.01/130.31 ms, fresh 25/128; per-cell 123.91/136.17 ms, fresh 76/128. В обоих 128/128 без drops; raw functional parity 128/128, missing pairs 52. Per-cell блокирует 2195 cell×frame ground appearances (1994 при publication, ещё 201 при receipt); это не 2195 уникальных физических препятствий. Все 256 derived receipts повторно проверены по payload hashes/ages/policy. +- Продуктовый backend/frontend path и registry не переключены. Этап 2 остаётся незавершённым: общий supervisor/lease fencing, binary live ingress без знания EOF и standalone package ещё не реализованы. Этапы 3–4 не начаты. Следующий bounded шаг — lifecycle/ownership + неизвестная длина входного потока; старый batch materializer не ослаблять. +- Evidence первого инкремента этапа 2: `.runtime/perception-stage2-cells-worker-20260902T1055MSK/manifest.json`, 125 artifacts, SHA-256 `1a951fd9e807099e500fa66f8a40b1076071f96e4c8e0be4ab3094caaa33bf09`. Четыре сервиса восстановлены, Triton ready=200; Ollama/Frigate exited/restart=no, pilots=0, GPU auto P8, Mac 8000=200 и 8765 закрыт. Модели/сырые outputs не попали в Git. ## Surprises / открытые вопросы @@ -293,6 +298,6 @@ EoMT — семейство ViT-моделей сегментации изобр ## Outcomes / retrospective -Этап 1 завершён как инженерный baseline: полный causal граф, shared six-layer ABI, measured Worker envelope, исходный clock, bounded queues и проверенные conservative freshness/material guards. Условия проверяет чистый evaluator; runtime-controller integration ещё нет. Fixed-clock A/B ранее дал bounded latency PASS, auto C сейчас даёт p99 141.40 ms и только 27 полных свежих scenes. Это честный FAIL квалификации, не запрет на следующий этап экспериментальной платформы. Default PyTorch сохранён, TensorRT parity не принята. Следующий этап 2: общий streaming lifecycle/data plane, lease/clock-condition monitoring, per-cell expiry и самостоятельный image без code/model mounts. Network, несколько/полная запись и standalone proof не получены; NVCR403/image-layer blocker не перепроверялся. В последнем шаге clocks/quotas не менялись, четыре сервиса восстановлены, Ollama/Frigate выключены, Mac 8000 работает. Неисправный исторический test с внешними evidence symlinks учтён отдельно; full suite не объявлен зелёным. +Этап 1 остаётся завершённым engineering baseline. Первый инкремент этапа 2 отделил scheduler от LAB-пилота и устранил whole-scene блокировку из-за одной старой ячейки: 76/76 доступных sensor-paired scenes дали свежий envelope, но expired/unknown cells внутри него остаются NO_GO. 52 source gaps не маскируются. Новый p99 136.17 ms — FAIL 125 ms; разницу auto timings не выдаём за причинное ускорение. Все сырые результаты моделей/геометрии/motion/TGS/material сохранены точно. Полноценный supervisor, cross-process lease/fencing, binary live ingress и standalone image ещё нужны; это не GO на этап 3. Default PyTorch сохранён, TensorRT parity не принята. Clock/quotas не менялись, четыре сервиса восстановлены, Ollama/Frigate выключены, Mac 8000 работает. Full suite не запускался; старый external-evidence-symlink baseline failure не исправлялся. Исторический NVCR403/image-layer blocker не перепроверялся новым build. После этапа 4 здесь будут перечислены digest самостоятельного полного образа, измеренные статусы и ошибки по recordings, реально проверенные source/hardware/config комбинации, состояние сохранённого EoMT-варианта и оставшиеся physical-live/quality/vehicle-integration ограничения. Готовый Docker и готовая автономия не отождествляются. diff --git a/docs/adr/0049-stream-first-perception-profiles.md b/docs/adr/0049-stream-first-perception-profiles.md index 75009f5..4172328 100644 --- a/docs/adr/0049-stream-first-perception-profiles.md +++ b/docs/adr/0049-stream-first-perception-profiles.md @@ -147,12 +147,39 @@ must reassess at later use. Missing/stale output remains inspectable but cannot retain permissive advisory policy. This envelope is NOT a replacement for StreamStart identities, complete input lineage or controller lease fencing. -The current pilot propagates the oldest last-seen permissive TGS cell into the -costmap/policy age. Expiry currently suppresses the entire scene's permissions; -stage 2 must implement explicit per-cell expiration without granting authority -from retained occupied/unknown history. Existing model/geometry/motion/TGS/material -outputs remain identical to the pinned reference on the measured 128-frame window. -Freshness/completeness is not semantic correctness or physical safety. +The stage-1 pilot propagated the oldest last-seen permissive TGS cell into the +costmap/policy age and suppressed the entire scene on expiry. Stage-2 increment +`1f8101e` adds `missioncore.costmap-cell-freshness/v1`: bounded (8192 cells), +index-aligned original support timestamps, decimal int64 strings/null, included +in the costmap payload digest together with the guard mode. Unobserved support +is never assigned a timestamp. The pilot now defaults to `per-cell`; the old +`whole-scene` mode remains an explicit comparison control, not a product cutover. + +Both publication and receipt remove permission from expired ground cells and +mark them rejected/NO_GO. Occupied cells retain prohibition. The remaining +permissions propagate their original support age AND the mandatory segmentation, +geometry and motion dependencies. A missing/stale mandatory layer still blocks +the whole policy. A derived consumer view has new costmap/policy hashes while +preserving source identity/timestamps; the original published bytes stay immutable. +Reassessment cannot restore a suppressed action or move the observer clock back. +The enclosing StreamStart must bind the grid/profile/epoch/clock; this descriptor +alone does not establish those identities or authenticate a remote producer. + +In the measured 128-frame window, raw model/geometry/motion/TGS/material outputs +remain identical to pinned PyTorch. Effective costmap states and permissions +change deliberately on expiry. A fresh six-layer envelope can still contain +rejected/unknown cells; it is not a claim of full free-space coverage, semantic +correctness, vehicle clearance or physical safety. Recheck again at actual use. + +`bcacb02` promotes the proven mailbox and serial GPU stage to common perception +modules, with the pilot importing compatibility aliases rather than owning +another scheduler. Pending ingress + completed GPU outputs share two slots; +active inputs share 16 MiB and are released by their owning stage. Cancellation +discards pending work, a timed-out callback retains ownership, and CPU-owned +input is not freed by GPU shutdown. Diagnostic drop history is capped at 256 +entries with exact per-reason totals; it is not the durable terminal ledger. +These primitives are NOT the controller supervisor, a cross-process GPU lease, +StreamStart fencing or the binary data plane. Those stage-2 boundaries remain open. `worker_operating_envelope.py` checks a trusted post-warmup snapshot against preregistered hardware/driver/resource/clock conditions and StreamStart identities, diff --git a/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md index 4a76908..2848e19 100644 --- a/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md +++ b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md @@ -5,6 +5,9 @@ Worker: RTX 4090, 24564 MiB, NVIDIA driver 610.47. Статус на 2026-09-02 10:16 МСК: **этап 1 закрыт как контракты и технический baseline; GO на инженерную реализацию этапа 2, не полный runtime и не real-time qualification**. Все промежуточные статусы ниже сохранены как история измерений. +Продолжение на 2026-09-02 11:00 МСК: начат этап 2, вынесен общий scheduler +и реализован per-cell expiry. Два новых Worker-прогона и точная parity приведены +в последнем разделе этого же журнала. Этап 2 целиком ещё не закрыт. Обновление 20:51 UTC: совместный source-paced пилот выполнен. После оптимизации 128/128 кадров без drops; p95/p99 174.09/190.62 ms — FAIL исходного latency gate. Подробности и evidence нового experiment `perception-joint-pilot-20260901T2040Z` @@ -1106,3 +1109,110 @@ GPU P8/210/405 MHz, 979 MiB, power limit 450 W; Mac 8000=200, 8765 закрыт. streaming без full-source barrier и standalone image без developer mounts. Auto-clock p99, source gaps, TensorRT parity, full-session/network/quality приёмка остаются открытыми. Этапы 3–4 не начаты, actuation=false. + +## Этап 2, первый инкремент — общий scheduler и per-cell expiry, 2026-09-02 11:00 МСК + +Изменения: `bcacb02` и `1f8101e`. Это продолжение исходного ExecPlan, не +отдельная LAB и не новый параллельный runtime domain. Старые graph/provider +контракты, модели, surface/geometry/motion/TGS/material алгоритмы сохранены. + +### Выполнено + +- Queue и GPU stage перенесены в `k1link.perception.streaming_queue` и + `streaming_scheduler`; пилот использует только compatibility imports. + Один serial GPU callback исполняет DDRNet → RF-DETR, CPU tail может + перекрываться с GPU следующего кадра. Две pending slots общие для ingress + и completed GPU, active inputs остаются в лимите 16 MiB до release владельцем. +- Finish дренирует очередь, cancel отбрасывает pending. При ошибке GPU его + active input освобождается; при stop timeout ресурсы остаются за реально + работающим callback. GPU close не освобождает CPU-owned input. Double/foreign + release и повторный/out-of-order admission отвергаются. Drop-history содержит + максимум 256 записей, totals сохраняются отдельно; это не terminal ledger. +- `CostmapCellEvidence` хранит исходный last-seen timestamp каждой ячейки, + строго ограниченные массивы и lossless int64 wire strings/null. Metadata и + guard mode включены в costmap hash. Нет подстановки времени для unseen cells. +- При publication/receipt старые ground cells становятся rejected/NO_GO. + Occupied/unknown не превращаются в разрешение. Остальные разрешения сохраняют + свой исходный возраст и все mandatory dependencies: stale segmentation или + missing geometry блокируют весь policy. TTL 250 ms не расширен. +- Derived consumer view получает собственные проверяемые hashes, но не меняет + epoch/source identity/timestamps и исходные wire bytes. Повторная проверка + не восстанавливает подавленное действие и не допускает обратного хода clock. + Основной pilot default теперь `per-cell`; `whole-scene` оставлен явным A/B control. + +Это низкоуровневые lifecycle primitives, **не** cross-process GPU lease, +authoritative controller или полный supervisor. Бинарный live data plane и +самостоятельный image без code/model mounts в этом инкременте не реализованы. + +### Пререгистрированный последовательный A/B на Worker 006 + +Experiment: `perception-stage2-cells-worker-20260902T1055MSK`. Каждый run — +128 кадров source-paced 1×, исходный host-arrival clock, одинаковые pinned +source/model assets и общий новый scheduler. PyTorch eager, DDRNet и RF-DETR +по 128 inference без held-mask cadence. Docker: прежние 8 CPU / 8 GiB, +network none, read-only assets/root; полный source не передавался и не +хешировался перед первым результатом. Никакого build/скачивания/clock lock. + +| Метрика | Whole-scene control | Per-cell | +| --- | --- | --- | +| Completed / drops / unaccounted | 128 / 0 / 0 | 128 / 0 / 0 | +| Latency mean / p95 / p99 | 82.74 / 125.01 / 130.31 ms | 77.52 / 123.91 / 136.17 ms | +| Fresh envelope publication → receipt | 26 → 25 | 76 → 76 | +| Missing sensor pairs | 52 | 52 | +| Whole costmap stale failures | 51 | 0; old cells individually NO_GO | +| First result после stream start | 567.24 ms | 568.13 ms | +| Warmup / stop | 9.333 / 4.066 s | 9.358 / 4.066 s | +| GPU peak / cgroup memory peak | 2362 / 3384.85 MiB | 2365 / 3377.78 MiB | +| Inflight peak / residual | 5,254,336 / 0 bytes | 5,202,376 / 0 bytes | + +Оба latency gate FAIL: p99 >125 ms. Auto clocks колебались, поэтому разница +mean/p95/p99 не приписывается новому scheduler или expiry. В обоих runs +SM/VRAM опускались ниже прежнего measured fixed envelope; CPU throttling=0. +Freshness+encode+receive целиком: mean/p95/p99 2.557/3.879/4.412 ms (control) +и 3.204/4.682/4.973 ms (per-cell); это не изолированная стоимость нового кода. +Максимальный scene payload 129,289 bytes, ниже 1 MiB collector cap. + +Per-cell: 1994 ground cell×frame appearances истекли при publication и ещё +201 при receipt; 1478 потенциальных разрешений были адресно подавлены. +Это temporal cell appearances, не число уникальных объектов/препятствий. +76 свежих envelopes соответствуют всем 76 доступным sensor pairs в этом +окне. **Внутри свежего envelope остаются rejected/unknown клетки**: это не +полное покрытие свободного пространства и не качество/безопасность движения. +52 missing pairs по прежнему source binding не подменяются новой геометрией. + +Оба runs: все 128 segmentation hashes, proposals, observations, tracks, +threats, range estimators, raw TGS state hashes, material arrays и sensor +bindings точны к pinned PyTorch `reference-locked-128-e`. Effective states +и policy намеренно меняются только от expiry/guard. Повторная read-only +проверка 256 сохранённых receipts восстановила derived views, их hashes, +freshness и policy counts. Ни одно разрешение не осталось на stale support, +не-ground, не-hard_surface или при неполном mandatory layer set. Motor authority=false. + +### Проверки, evidence и следующий gate + +202 focused tests PASS (contracts, freshness, queue/cancel/failure/release, +pilot, Worker envelope, material policy, local surface). Ruff, strict mypy +четырёх изменённых core modules, diff-check PASS. Full suite/build/models на +Mac не запускались. Известный historical baseline failure с внешними evidence +symlinks не ремонтировался и в этом шаге не перезапускался. + +Manifest: `.runtime/perception-stage2-cells-worker-20260902T1055MSK/manifest.json`, +125 artifacts; SHA-256 +`1a951fd9e807099e500fa66f8a40b1076071f96e4c8e0be4ab3094caaa33bf09`. +Копия: `D:/NDC_MISSIONCORE/runtime/experiments/perception-stage2-cells-worker-20260902T1055MSK`. +Image SHA `664824aa25de1db178f177d67a81b01541a938b479812b9383ddbf03f6b59dbe` +и candidate profile SHA `e1c244e3be8b4880cb4b4d7e96a88feada69773dbb16f5c9a17ef663030138f3` +не изменились; guard mode и code identities записаны отдельно в commands/manifest. +Raw evidence остаётся вне Git. + +Все четыре ранее работавших Mission Core сервиса восстановлены в dependency +order, Triton healthy/ready=200. Старые service restart loops не менялись. +Ollama/Frigate exited/restart=no; pilots=0. Final GPU auto P8/210/405 MHz, +980 MiB, power limit 450 W. Mac 8000=200, 8765 закрыт. + +**Gate:** первый инкремент этапа 2 принят, весь этап ещё в работе. Следующий +шаг — общий supervisor/StreamStart lifecycle с authoritative ownership и +fencing, затем binary live ingress без знания длины/EOF и standalone package. +Не выдавать их за реализованные по факту общего scheduler. Stage 3 cutover, +full-session/network/quality/vehicle qualification и TensorRT promotion закрыты +до своих проверок. Профиль остаётся экспериментальным, actuation=false.