docs(perception): record bounded binary ingress evidence and remaining bridge

This commit is contained in:
DCCONSTRUCTIONS
2026-09-02 12:37:25 +03:00
parent 79ce55d197
commit c23e86fd39
3 changed files with 162 additions and 4 deletions
@@ -1,8 +1,8 @@
# Observatory: четыре этапа создания полного real-time Perception-профиля
Дата: 2026-09-01; обновлено 2026-09-02 12:00 МСК. **Этап 1 закрыт; этап 2 в работе: общие scheduler/per-cell expiry дополнены subprocess lifecycle и Worker-local cooperative lease/fencing. Real-time qualification НЕ выдана.** Полный normal pilot: 128/128 без drops, p95/p99 124.98/136.12 ms, fresh 76/128; 52 source gaps остаются NO_GO. Два намеренно аварийных прогона подтвердили lease-loss, полное освобождение и точный terminal accounting. Межконтейнерные contention/clean succession/crash quarantine проверены. Постоянный product controller, binary live ingress и standalone image ещё не готовы; этапы 3–4 не начаты. Default PyTorch, TensorRT parity не принята.
Дата: 2026-09-01; обновлено 2026-09-02 12:35 МСК. **Этап 1 закрыт; этап 2 в работе. Третий инкремент: bounded binary IPC ingress с неизвестной длиной источника подключён к общему lifecycle/byte budget и проверен на Worker.** 103/103 исходных события доставлены без изменения bytes/metadata; камера, LiDAR и pose поступают до End. Это raw-digest consumer, **не** подключённый к этому ingress полный модельный граф. Real-time qualification НЕ выдана: последнее полное измерение остаётся 128/128, p95/p99 124.98/136.12 ms, fresh 76/128. Далее decoder→full graph bridge, network/controller и standalone image; этапы 34 не начаты. Default PyTorch, TensorRT parity не принята.
Последние изменения: `6acf468` — lifecycle и Worker-local lease; `ac69e3b` — подключение к полному пилоту и negative probes. Final expiry trace: stop через 45.74 ms после deadline, retirement через 4109.82 ms, receipts at/after deadline=0. Проверены все 229 опубликованных receipts и точная raw parity с соответствующими prefix reference. Модели/thresholds/clocks/quotas не менялись; auto latency deltas не являются доказанным ускорением. Следующий шаг — bounded binary ingress с неизвестной длиной источника, постоянная controller integration/recovery и standalone package. Локальный cooperative fence не заменяет backend claims, external GPU inventory или network authentication; эти gates остаются открытыми.
Последние изменения: `da60fef` — binary v2 mapping существующих LiveIngressEvent, sender/receiver и общий byte budget; `a937400` — корректная фиксация End в probe; `79ce55d` — regression старого raw-first ingress. 276 focused tests PASS. CPU-only Worker probe: 32 camera frames + init + 34 LiDAR + 36 pose, 4,061,693 wire bytes, peak input 553,991 bytes, residue 0. Межпроцессная доставка до raw callback: p95/p99 0.419/0.601 ms; это не model/network latency. Обрыв между фрагментами не выдал payload и завершил lease. Модели/clocks/старые GPU-сервисы не менялись. Прежние lifecycle/lease/full-graph доказательства сохранены; product batch path пока не переключён.
Текущий 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,7 +143,7 @@ IPC/сети, копирований и оркестрации. Вычислит
## Этап 2 — Самостоятельный Docker с полным потоковым вычислением
**Текущий статус, 12:00 МСК:** в работе. Общие mailbox/serial GPU stage, per-cell expiry, subprocess lifecycle и Worker-local cooperative lease подключены к полному пилоту. Межконтейнерное владение, crash quarantine и две реальные lease-expiry остановки проверены. Production admission/recovery, continuous GPU inventory/envelope monitoring, binary network ingress и standalone image ещё не закрыты. GO на этап 3 пока нет.
**Текущий статус, 12:35 МСК:** в работе. Lifecycle/scheduler/per-cell expiry проверены полным пилотом; новый raw binary ingress — отдельным CPU-only межпроцессным probe. Их decoder/full-graph соединение ещё требуется: новый вход пока принимает и проверяет raw события, не рассчитывает модели. Production admission/recovery, continuous GPU inventory/envelope monitoring, binary network ingress и standalone image ещё не закрыты. GO на этап 3 пока нет.
**Цель:** один самостоятельный контейнер принимает поток и реально рассчитывает DDRNet, детекции, расстояния, motion, TGS/costmap и policy-shadow; ничего не дорисовывается из старых LAB.
@@ -260,8 +260,12 @@ EoMT — семейство ViT-моделей сегментации изобр
- Normal pilot 128/128 без drops, p95/p99 124.98/136.12 ms, fresh 76/128. Intentional expiry A: 52 released = 51 complete + 1 GPU terminal drop; expiry trace B: 50 released = 50 complete. Оба `execution_complete=false`, reason=`lease-lost`, unaccounted=0, все процессы/входы освобождены. Final trace: stop-request deadline +45.74 ms, retirement +4109.82 ms, receipts at/after deadline=0. Все 229 опубликованных raw outputs exact к reference prefix; clocks/quotas/models не менялись.
- Evidence: `.runtime/perception-stage2-lifecycle-worker-20260902T1146MSK/manifest.json`, 259 artifacts, SHA-256 `00bd091a80845e50489a34ce4df2cbf3d2cd60d9ecb13d1d97accd03d44fdba4`. Временные probe containers и два test volumes удалены после сохранения owner records. Четыре сервиса восстановлены; Triton ready=200, Ollama/Frigate exited/restart=no, Mac 8000=200, 8765 закрыт. Этап 2 остаётся в работе; дальше binary ingress, постоянная controller/recovery integration и standalone package.
- 2026-09-02 12:35 МСК: третий инкремент (`da60fef`, `a937400`, `79ce55d`), 276 focused tests PASS. Worker raw IPC: 103/103 exact, каждый data channel до End, peak 553,991 bytes; negative EOF: incomplete=1, delivered=0, release=true. Evidence `.runtime/perception-stage2-binary-ingress-worker-20260902T1232MSK/manifest.json`, 42 artifacts, SHA-256 `2a5492080027a86de9f176f051c9265e29f377d1d9207c86ac93cdff7632505a`. Попытки 1230 (неполный diagnostic code pack) и 1231 (гонка финального timestamp journal) сохранены как rejected; их manifests связаны из принятого. Никакой повторной GPU-квалификации этим probe не выдано.
## Surprises / открытые вопросы
- IPC probe отделил работоспособность raw ingress от работоспособности decoder/full graph. Наличие codec-init gate не проверяет NAL/IDR, access-unit framing или соответствие fisheye calibration. Оригинальные fMP4 segments не превращаются автоматически в model-ready frames; следующий bounded шаг — persistent incremental decoder и causal sensor adapter с allocation bounds, затем тот же полный граф. Старые model inputs/prepared paths не подмешивать в доказательство нового ingress.
- 2026-09-02 12:00 МСК: истечение lease и освобождение GPU разделены. После crash OS lock свободен, но durable `active` не допускает новый запуск. Recovery намеренно отсутствует до trusted resource-release proof; нельзя удалять production marker ради продолжения. В пробах удалены только два заведомо временных experiment-owned volume после сохранения записей и остановки всех probe containers.
- Свежая camera/cloud/pose пара не равна свежему полному scene. У TGS last-seen разрешающих ячеек может быть старее camera anchor; новый guard сохраняет этот возраст. В финальном C пять scenes истекли за 14 ms между publisher guard и приёмом, хотя раньше выглядели бы свежими. Пока одна такая ячейка запрещает весь scene; per-cell expiry — следующий runtime increment без ослабления 250-ms TTL. 52 source gaps нельзя исправить GPU-ускорением.
@@ -303,6 +307,6 @@ EoMT — семейство ViT-моделей сегментации изобр
## Outcomes / retrospective
Этап 1 остаётся завершённым engineering baseline. В этапе 2 общий lifecycle теперь действительно управляет subprocess-backed пилотом: тёплые модели, admission, serial GPU/CPU lanes, result binding, watchdog и проверенный release. Cooperative lease проверен между контейнерами на общем томе; crash не превращается в разрешение новому владельцу. Normal run 128/128, 76 fresh envelopes, raw parity exact; p99 136.12 ms — всё ещё FAIL 125 ms. Expiry runs завершились намеренным FAIL с закрытым учётом и без остаточных владельцев/bytes, а не ложным successful completion. Следующий этап работы — binary unknown-duration ingress и постоянная controller/ownership/recovery integration, затем самостоятельная упаковка. Новый код не переключает старый batch/registry/UI; GO на этап 3 нет. Clocks/quotas/models не менялись, временные ресурсы убраны с сохранением evidence, четыре сервиса восстановлены, Ollama/Frigate выключены. Full suite и новый image build не запускались; исторические baseline-symlink и NVCR403 вопросы не объявлены исправленными.
Этап 1 остаётся завершённым engineering baseline. Этап 2 теперь имеет общий scheduler, per-cell expiry, subprocess lifecycle/lease и bounded raw binary IPC. Новый ingress прошёл 103 реальных source events без потерь/изменений и отдельный incomplete-fragment отказ. Общий byte budget удерживает raw/reassembly до выхода callback; старые input owners не освобождаются при cancel. Но raw-digest probe не равен полному графу: следующий шаг соединяет incremental decoder/causal sensor adapter с моделями и повторяет full-profile timing/parity на новом входе. Прежний полный p99 136.12 ms остаётся FAIL 125 ms. Network/gRPC/authentication, production controller/recovery/inventory и standalone image не приняты; старый batch/registry/UI не переключены. Четыре сервиса не останавливались в новом CPU-only probe, Ollama/Frigate остаются выключены. Full suite/image build не запускались; исторические baseline-symlink и NVCR403 вопросы не объявлены исправленными.
После этапа 4 здесь будут перечислены digest самостоятельного полного образа, измеренные статусы и ошибки по recordings, реально проверенные source/hardware/config комбинации, состояние сохранённого EoMT-варианта и оставшиеся physical-live/quality/vehicle-integration ограничения. Готовый Docker и готовая автономия не отождествляются.
@@ -99,6 +99,47 @@ explicit byte bound is required. No duplicate new scanner feed is introduced.
## Time and lifecycle
Stage-2 raw IPC increment, 2026-09-02 (`da60fef`, `a937400`, `79ce55d`):
`streaming_wire.py` maps existing `LiveIngressEvent` fields into
`missioncore.live-perception-wire/v2`. The v1 producer hooks, class and legacy
serialization remain unchanged. A bounded length-prefixed JSON header carries
decimal uint64 projections; payloads remain binary. This is a controller-supplied
IPC socket candidate, not a selection/replacement of the intended gRPC network
transport. No listener, arbitrary endpoint, scanner feed or command path is added.
Open compares the entire expected StreamStart and acquisition session binding;
every fragment/control carries a digest of that full binding. A hash is integrity,
not authentication. Fragment size is at most 1 MiB, event caps reuse the existing
1 MiB camera / 2 MiB LiDAR/pose limits. Headers are capped at 64 KiB. One
observation assembles at a time with exact offsets, fragment and whole-event
SHA-256, per-channel source identity/sequence/clock checks. End, Cancel and
gap/unavailable notices are explicit. EOF without End, timeout, malformed,
cross-binding or incomplete input fails the bound stream; an unbound wrong Open
is rejected without stopping the current owner. Camera frames require init;
camera gap invalidates init. Actual codec/keyframe/IDR validation is NOT yet here.
`StreamingSender` owns no queue and fails on its bounded write deadline rather
than stretching replay time. `StreamingIngress` is a lifecycle-tracked thread;
idle reads poll the lease and cannot keep accepting an expired owner. Raw/header
and reassembly reservations charge the SAME StreamMailbox 16 MiB input budget as
queued/active bundles. They survive cancellation until the borrowing callback
returns and buffers are dropped. Reservations are count-bounded too. Trusted
decoder adapters must reserve scratch BEFORE allocation and must not retain raw
callback bytes outside that ownership contract. Python metadata object overhead,
socket/kernel buffers, source adapter memory and model tensors additionally need
RSS/OS resource bounds; this application counter alone is not a total-RSS claim.
Worker evidence uses a separate source process, original camera init/fMP4 segments
and existing normalized point/pose increments paced at original 1x times. All
103 events (32 camera + init + 34 LiDAR + 36 pose) match exact bytes/metadata, each
data modality reaches the hash-only consumer before End, and incomplete EOF
delivers no observation. Normal peak input is 553,991 bytes. This validates raw
IPC, NOT decoder output, the full graph on this ingress, model performance,
authenticated network behavior or a standalone image. The next adapter must
feed incremental decode and causal sensors into the same graph without using
the old concatenated camera file or precomputed geometry. Product source queues,
backend routes and the browser are not switched by this increment.
Open → validate bounded metadata/claim → warm models → Ready → start the replay
clock → observations and incremental scenes → stop/drain bounded state → close
and asynchronously seal the immutable receipt. A live source already producing
@@ -8,6 +8,9 @@ GO на инженерную реализацию этапа 2, не полны
Продолжение на 2026-09-02 11:00 МСК: начат этап 2, вынесен общий scheduler
и реализован per-cell expiry. Два новых Worker-прогона и точная parity приведены
в последнем разделе этого же журнала. Этап 2 целиком ещё не закрыт.
Продолжение на 12:35 МСК: третий инкремент — общий bounded binary raw IPC,
103/103 исходных событий до End и negative EOF на Worker. Это raw-digest probe,
не новый полный model run. Decoder/full-graph bridge ещё требуется.
Продолжение на 12:00 МСК: добавлены subprocess lifecycle, Worker-local
cooperative ownership и fencing; normal/две expiry пробы и межконтейнерное
владение проверены. Последний раздел фиксирует этот второй инкремент этапа 2.
@@ -1341,3 +1344,113 @@ trusted recovery/inventory enforcement и standalone image без code/model mou
Stage 3 UI/registry/batch cutover не начинался. Все real-time/network/full-session/
quality/vehicle gates и actuation=false сохраняются; новый image build и
исторический NVCR403 blocker в этом шаге не проверялись.
## Этап 2, третий инкремент — bounded binary raw IPC, 2026-09-02 12:35 МСК
Коммиты: `da60fef` — общий wire/sender/receiver и raw byte reservations;
`a937400` — End-marker до закрытия probe, unique run/epoch по experiment;
`79ce55d` — reuse существующего raw-first ingress без изменения wire v1.
Ни одного нового model run, изменения весов/thresholds/clocks или переключения
product LAB path в этом инкременте нет.
### Что реально реализовано
`missioncore.live-perception-wire/v2` сохраняет поля `LiveIngressEvent`:
session/generation, ingress и source sequences, modality/source, original capture
и source-host arrival stamps. JSON metadata использует decimal uint64 strings;
payload бинарный, без base64, PNG-конверсии или целого архива. Header ≤64 KiB,
fragment ≤1 MiB, raw camera event ≤1 MiB, LiDAR/pose ≤2 MiB — прежние modality
bounds, не новый источник/протокол K1. Full StreamStart и acquisition mapping
сверяются на Open; binding SHA повторяется на каждом fragment/control.
Это integrity/fencing, не сетевая authentication.
Один receiver собирает одно событие; проверяет offsets, размер, SHA каждого
fragment и целого observation, source identity/sequence/clock. Camera без init
отклоняется; gap требует нового init. Парсинг NAL/IDR/codec и превращение fMP4
в кадры пока не реализованы этим слоем. End — явное событие, не prerequisite
для доставки; Cancel и modality gap/unavailable отдельны. Неожиданный EOF,
timeout, порча и переполнение завершают bound stream, не растягивают source time.
Неверный Open ещё не bound peer и не может отменить текущего владельца.
Sender синхронный, без фоновой очереди; source adapter отвечает за pacing и
владение исходным payload. Receiver thread tracked общим lifecycle, idle read
перепроверяет lease. Reassembly и raw/header copies резервируются **до**
аллокации в том же 16-MiB бюджете, что queued/active bundles. Cancel не освобождает
live reservations. Callback получает borrowed raw bytes только на время вызова;
будущий decoder обязан отдельно резервировать scratch до выделения памяти и
не удерживать raw вне этого контракта. Counter не заменяет RSS: Python object,
kernel/socket, source cache и model tensor budgets проверяются отдельно.
### Worker 006: фактический inter-process input
Принятый experiment: `perception-stage2-binary-ingress-worker-20260902T1232MSK`.
Один временный CPU-only контейнер, network none, без GPU request, 2 CPU / 768 MiB,
read-only image, ограниченный tmpfs; новый image не строился. Источник и receiver
разделены процессом/socket. Source adapter читает существующие camera init/media
по одному chunk с проверкой index SHA и incrementally — прежний normalized
sensor NPZ. Точки сохраняют xyz f64 + intensity u8, pose — position/quaternion;
это normalized archive inputs, не выданные за исходный vendor packet/K1 live feed.
Отсутствующий у этих sensor rows UTC не придумывается (0), original host stamps
сохранены. Calibration в hash-only probe не используется и явно имеет synthetic
identity; model scene по этому probe не допускается.
Источник ограничен 32 camera events для canary, но receiver не получает ни
frame count, ни duration, ни inventory. Prefix и bounded prerelease sensor rows
не скрываются: считано 146/4598 pose rows, 139/4570 point batches,
333168/10751258 xyz rows. Это не полный pass, не full-file hash и не полный decode.
| Метрика | Принятый raw IPC probe |
| --- | --- |
| Sent / received | 103 / 103, exact bytes/metadata |
| Состав | init 1, camera 32, LiDAR 34, pose 36 |
| Доставка каждого data channel до End | PASS |
| Wire bytes | 4,061,693 |
| Пик input byte budget / остаток | 553,991 / 0 bytes |
| Cgroup memory peak normal | 51,773,440 bytes |
| Source release lag max | 3.717 ms |
| Межпроцессный send-start → hash callback p50/p95/p99/max | 0.292 / 0.419 / 0.601 / 0.669 ms |
| Sender write p95/p99 | 0.190 / 0.316 ms |
Интервалы измерены на одной Linux kernel monotonic timeline, не вычитанием
несогласованных source/remote clocks. Эти sub-ms значения не включают decode,
модели, TGS, scene delivery, сетевой маршрут или browser. Их нельзя прибавить
к прошлому p99 и объявить новую real-time квалификацию без полного замера.
Отдельная synthetic negative проба оборвала LiDAR observation 1,048,593 bytes
после первого 1-MiB fragment: started=1, completed=0, incomplete=1,
terminal=failed, никакого payload callback. Peak bytes 2,293,803 (включая
консервативный copy reserve), после cleanup 0. Обе пробы: lease released,
owned children=0 live, active GPU/CPU calls=0. Временный source process и
контейнер убраны; никаких постоянных volumes/leases этим probe не создано.
### Неуспешные попытки и финальная фиксация
Попытка `1230MSK` отклонена до observations: в diagnostic code pack не хватило
`k1link.data_plane` (и зависимого perception contracts); точный import failure
подтверждён отдельным CPU-only check. Исправлен только состав snapshot.
PowerShell stderr redirection также исправлена для сохранения traceback.
Попытка `1231MSK` передала 103/103 и корректно обработала negative EOF, но
финальный source timestamp мог не сохраниться: source закрывал socket до записи
marker, а supervisor уже останавливал child. Acceptance остановлена на missing
evidence. Marker перенесён до End; следующий отдельный experiment повторил обе
пробы. Старые folders/logs/owner results не перезаписывались.
276 focused tests PASS (включая 40 новых ingress cases и legacy live-perception
regressions); Ruff, mypy четырёх core modules, diff-check PASS. Full suite не
запускался; прежние baseline-symlink/NVCR403 вопросы не пересматривались.
Manifest: `.runtime/perception-stage2-binary-ingress-worker-20260902T1232MSK/manifest.json`,
42 artifacts, SHA-256
`2a5492080027a86de9f176f051c9265e29f377d1d9207c86ac93cdff7632505a`.
Он ссылается на отдельные sealed rejected manifests 1230/1231. Копии evidence
находятся в одноимённых папках `D:/NDC_MISSIONCORE/runtime/experiments/`.
Model/raw inputs в Git не добавлялись. Четыре Mission Core сервиса продолжали
работу, Triton ready=200; Ollama/Frigate exited/restart=no. Probe/import-check
containers=0. GPU auto P8, 979 MiB, 450 W; Mac 8000=200, 8765 закрыт.
**Gate:** принят bounded raw IPC core. Следующий шаг — persistent incremental
camera decoder и causal sensor adapter, соединяющие этот ingress с тем же
полным DDRNet/RF-DETR/geometry/motion/TGS/policy графом, затем full-graph
parity/timing на новом входе. Network/gRPC/authentication, constant controller
root/recovery/inventory, standalone image и product cutover остаются открытыми.
Этап 2 не закрыт, этапы 3–4 не начаты; actuation=false.