docs(perception): record recoverable input policy and decoder continuity proof

This commit is contained in:
DCCONSTRUCTIONS
2026-09-02 15:33:53 +03:00
parent c31c46caa5
commit 03a7e730ae
3 changed files with 180 additions and 7 deletions
@@ -1,8 +1,8 @@
# Observatory: четыре этапа создания полного real-time Perception-профиля
Дата: 2026-09-01; обновлено 2026-09-02 14:52 МСК. **Этап 1 закрыт; этап 2 в работе. Седьмой инкремент: controller readiness связан с общим streaming lifecycle.** Просроченный/неизвестный inventory, потеря владельца или идентичности останавливают admission/compute/results; heartbeat не заменяет свежую телеметрию. Явный `labelled-experiment` допускает низкие clocks/выход из performance envelope, но не выдаёт qualification. Worker CPU-only: четыре сценария PASS, cleanup 10.67663.994 ms, input/children/lease released. Это synthetic GPU facts + реальные Linux child processes, не production GPU collector и не новый замер полного графа. Далее trusted collector/control-plane adapter, recovery, network и standalone image; этапы 3–4 не начаты.
Дата: 2026-09-01; обновлено 2026-09-02 15:30 МСК. **Этап 1 закрыт; этап 2 в работе. Восьмой инкремент: пауза/восстановление входа отделены от жизни resident-профиля.** По уточнению владельца временный обрыв потока или неизвестная/просроченная GPU-телеметрия не должны убивать процессы. Новый явно включаемый режим сохраняет локальный lease и детей, отбрасывает старый вход/результаты и требует новую input epoch со свежим keyframe/pose/points перед resume. Подтверждённый конфликт владельца, настоящая потеря локального lease, падение child и cancel остаются terminal. Worker CPU-only: три эпохи, обрывы 150 ms / 2.2 s, неизменные PID реального H.264 decoder и CPU sentinel. Это не восстановление полного GPU-графа: его adapter/reset ещё предстоит подключить. Далее full-graph recovery, trusted collector/control plane, network и standalone image; этапы 3–4 не начаты.
Последний код `92625bf`; 349 focused tests PASS, Ruff/format/mypy PASS. В probe нет GPU devices, моделей, записей, Docker socket или новых образов; сервисы/частоты не менялись. Предыдущие полные binary-прогоны сохраняют 128/128 exact raw parity; p95/p99 85.113/91.219 и 82.425/90.530 ms относятся только к временно фиксированным штатным clocks. Fresh 76/128 и исходные 52 sensor gaps остаются, прежний auto-clock FAIL не отменён. Product batch path не переключён; существующий PilotController ещё не получает настоящую непрерывную GPU-телеметрию.
Последний код `c31c46c`; 375 focused tests PASS, Ruff/format/mypy PASS. CPU probe декодирует один реальный H.264 fragment трижды с синтетическими текущими timestamps/pose/points; это не полный replay. BGR exact 3/3, peak input 5,275,461 bytes, финально input/children=0, lease released. GPU devices/модели не запускались, сервисы/частоты не менялись. Предыдущие полные binary-прогоны сохраняют 128/128 exact raw parity; p95/p99 85.113/91.219 и 82.425/90.530 ms относятся только к временно фиксированным штатным clocks. Fresh 76/128 и исходные 52 sensor gaps остаются, прежний auto-clock FAIL не отменён. Product batch path не переключён; существующий full PilotController пока не использует ни resumable adapter, ни настоящий continuous GPU collector.
Текущий 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 с полным потоковым вычислением
**Текущий статус, 14:52 МСК:** в работе. Binary full graph имеет exact raw parity 128/128; локальная задержка ≤125 ms измерена только при фиксированном operating envelope. Теперь `WorkerReadinessMonitor` проверяется в `StreamingLifecycle` перед startup/ready, admission, compute, result, renewal и каждые 50 ms watchdog. Есть strict/labelled-experiment режимы, terminal loss без resurrection и сохранение lease до verified cleanup. Контроль проверен синтетически и CPU-only на Worker. Следующая незакрытая граница — реальный trusted GPU/inventory collector и control-plane adapter для полного профиля, затем recovery/network/standalone. Не объявлять optional monitor в core подключённым production controller; unmonitored runtime явно сообщает `enabled=false`. GO на этап 3 пока нет.
**Текущий статус, 15:30 МСК:** в работе. Binary full graph имеет exact raw parity 128/128; локальная задержка ≤125 ms измерена только при фиксированном operating envelope. Common lifecycle/readiness теперь имеют явный recoverable режим: input waiting/synchronizing не равны STOPPING. Lease/controller heartbeat локальны Worker, независимы от связи со станцией/ровером; неизвестная телеметрия блокирует новые вычисления, но не освобождает GPU и не убивает детей. Fresh telemetry сама не возобновляет старую epoch. Проверены common primitives и реальный CPU decoder; полный PilotController/BinaryGraphBridge ещё остаются non-resumable. Следующая незакрытая граница — подключение pause/resume, отбрасывания старых GPU/CPU результатов и настоящего temporal/TGS reset к полному графу, затем trusted collector/control plane, network/standalone. Optional primitive не означает product cutover. GO на этап 3 пока нет.
**Цель:** один самостоятельный контейнер принимает поток и реально рассчитывает DDRNet, детекции, расстояния, motion, TGS/costmap и policy-shadow; ничего не дорисовывается из старых LAB.
@@ -158,6 +158,7 @@ IPC/сети, копирований и оркестрации. Вычислит
- Связать результаты слоёв в общий scene contract во время исполнения, а не только склеить тайминги после завершения. Привязать semantic labels к текущей геометрии с temporal/coordinate validity и bounded TTL. TGS и semantic policy становятся реальными входами диагностического rule evaluation, не только соседними слоями viewer.
- Подключить существующее coarse material mapping и простую advisory policy: `hard_surface` — допустимый материал для первого сельского прототипа; geometry/TGS occupied и missing/stale evidence имеют приоритет над этим допуском. Тротуар и велодорожка не являются отдельными отказными случаями. Не добавлять второй segmenter или новую fine-grained road policy. Допуск поверхности не выбирает объезд и не выдаёт motor commands.
- Сделать ограниченные очереди, явные cadence/drop/TTL правила, backpressure и stop/cancel. Завершение lease, смерть процесса и смена владельца должны прекращать старое исполнение; новый профиль не стартует, пока старый GPU-владелец не освобождён. Restart не воспроизводит накопившийся устаревший live backlog.
- Для временного input/network gap сохранять прогретые процессы и локального владельца. Replay clock продолжает 1×; очередь не накапливает прошлое. Повторное подключение создаёт отдельную input epoch без смены model activation/lease generation. До resume нужны свежий декодированный keyframe, causal pose/points, сброшенные tracking/motion/rolling TGS/costmap и повторная проверка свежести. Деградация телеметрии допускает ожидание без выдачи qualified результатов; подтверждённый ownership/runtime fault не маскируется как сетевой лаг. Физический stop/hold и политика возобновления ровера — отдельный будущий onboard safety gate.
- Выдавать результаты и технические метрики до EOF; хранение/overlay/video export не блокируют inference. Для сохранения evidence тоже задаётся ограничение ресурсов и честное состояние при переполнении. Не выдавать повтор предыдущей маски за новое измерение.
- Упаковать первый полный образ с pinned model assets, TGS/runtime и нужными библиотеками. Проверить запуск без developer checkout, host model cache, внешнего Triton и model downloads. Не добавлять backend/БД/broker в контейнер. EoMT остаётся сохранённым отдельным вариантом вне активного первого профиля.
@@ -224,6 +225,7 @@ EoMT — семейство ViT-моделей сегментации изобр
## Progress
- 2026-09-02 15:30 МСК: `c31c46c`, resumable lifecycle/input epoch, recoverable readiness, decoder/sensor reset. 375 focused tests PASS, Ruff/format 14 files и mypy 7 modules PASS. Worker CPU-only три input epochs, EOF-паузы 150 ms / 2.2 s, 3/44 synthetic source ticks во время пауз, 54 local renewals; PID decoder/sentinel неизменны, BGR exact 3/3. Peak input 5,275,461 bytes, final input/children=0, released lease; temporary container удалён. Один реальный H.264 fixture + synthetic timestamps/sensors/temporal reset, НЕ полный graph/GPU recovery. 73 code hashes сверены, 85 evidence artifacts; `.runtime/perception-stage2-continuity-worker-20260902T1518MSK/manifest.json`, SHA-256 `fbd327d129c88caa13b7183b1ae2c4767e877a6f5472c0f430875cfd7401ed46`. Сервисы/clocks не менялись; прежние legacy restart loops не исправлялись. Старый terminal-readiness эксперимент ниже сохранён как история; новый TARGET по решению владельца — wait/resync для временной недоступности.
- 2026-09-02 14:52 МСК: `92625bf`, readiness/lifecycle increment. 349 focused tests PASS; Worker Linux CPU-only 4/4 scenarios, stop 10.67663.994 ms, 0 residual bytes, terminal fixture lease generation 4 released. Expired inventory остановил runtime через 1043.960 ms после последнего refresh, несмотря на 13 heartbeat renewals; late refresh/result rejected. Allowed overload сохранил violation после восстановления clocks. 70 measured code files verified, 86 evidence artifacts; `.runtime/perception-stage2-readiness-worker-20260902T1450MSK/manifest.json`, SHA-256 `4588995d763fe82d896b42689e981f1d00feedaf9d6aab29f4579f771d03da3a`. GPU facts synthetic, no model timing or collector qualification. Service IDs/StartedAt/restart counts неизменны до/после; у legacy agents уже были restart counts 21/2/2 — состояние running не объявляется устойчивой готовностью. Clock setters, service mutations, network listeners, registry/UI отсутствуют.
- 2026-09-02 14:22 МСК: `380b6ea` / `f39f1ff`. CPU probe (NumPy 1.26.4, Worker x86) воспроизвёл две ошибки range_m через quaternion address 8 mod 16; aligned copy сохраняет bytes и прежние norm/projection результаты. Удалены четыре full-frame copies на связке decoder→parent→DDRNet; binary framing, source clock, TTL, lease checks не менялись. A–B–B–A, 4×128 без drops: контроль p95/p99 84.702/92.961 и 83.930/91.759 ms; кандидат 85.113/91.219 и 82.425/90.530 ms. Кандидат raw parity 128/128 дважды, available/fresh 76/128; global qualification=false. CPU oracle 128/128 BGR/sensors для обоих вариантов, hung decoder cleanup PASS. 279 focused tests PASS. Manifest 305 artifacts, SHA-256 `9c72a93833a1dda51c4787dca13fb9791a1bf2e31c763b7740e1b21406703707`, `.runtime/perception-stage2-ipc-worker-20260902T1410MSK/manifest.json`. Частоты auto и сервисы восстановлены; registry/UI/image не менялись.
@@ -297,6 +299,7 @@ EoMT — семейство ViT-моделей сегментации изобр
## Decision log
- 2026-09-02, уточнение владельца: временная потеря входной сети/потока не завершает resident AI-профиль. Отдельно сохраняем local Worker lease, ждём свежий поток без backlog и заново синхронизируем temporal state. Unknown/stale GPU telemetry — не доказательство чужого владельца; подтверждённый конфликт/авария остаются terminal. Автоматическое восстановление inference не означает разрешение возобновить физическое движение.
- 2026-09-01, решение владельца: EoMT и DDRNet не считаются вместе на Worker 006. Первоначальная трактовка «никаких двух моделей внутри профиля» отменена последующим уточнением: RF-DETR и DDRNet нужны внутри одного полного профиля; запрет сохраняется для альтернативных профилей и EoMT+DDRNet.
- 2026-09-01, решение владельца: один дрон — один Worker; текущий baseline RTX 4090. Следствие: worker-scoped exclusivity, без GPU-multiplexing и без зависимости от покупки hardware.
- 2026-09-01, решение владельца: EoMT сохранить отдельно, даже если не проходит real-time на текущей карте. Следствие: отрицательный benchmark оформляется как честный статус, а не повод блокировать DDRNet или бесконечно оптимизировать.
@@ -312,6 +315,8 @@ EoMT — семейство ViT-моделей сегментации изобр
## Восстановление и остановки
Для уже активного профиля временный обрыв входа или задержка/неполнота telemetry означают ожидание/resync с сохранением моделей и lease, а не уничтожение процесса. Неизвестный владелец запрещает admission нового профиля; старый локальный владелец не отдаёт ресурс на основании одного отсутствующего snapshot. Подтверждённая потеря локальной authority/конфликт, model/decoder failure и cancel — отдельные terminal причины. Включение нового поведения требует resumable adapter; текущий полный пилот ещё не переведён. Предыдущие terminal fault probes остаются историческими проверками прежнего режима.
При неудаче короткого canary остановить только принадлежащий испытанию профиль, сохранить диагностику и проверить освобождение GPU; не убивать посторонние процессы и не продолжать full-session. Неясный владелец GPU или потеря lease требуют fail-closed остановки нового запуска, а не захвата ресурса поверх старого процесса. Переключение на другой профиль — отдельная последовательная операция, не автоматический GPU fallback.
Новые схемы/декларации вводятся версионно. Возврат к точному предыдущему образу/конфигурации не превращает старый batch-путь в real-time; при откате сохраняется честный статус unavailable/not-qualified. Общую старую очередь нельзя ослаблять без worker-scoped fencing. Опубликованная история и исходники записи не переписываются для прохождения проверок.
@@ -320,6 +325,6 @@ EoMT — семейство ViT-моделей сегментации изобр
## Outcomes / retrospective
Этап 1 завершён; этап 2 продолжается. Полный binary graph сохраняет 128/128 raw outputs, original 1× и bounded input; предыдущий conditional timing baseline не расширен. В общий lifecycle добавлен readiness gate с независимыми lease/inventory deadlines и двумя явными performance modes. Четыре Worker CPU-only faults проверили stop/fencing/retirement, но GPU факты в них synthetic. Следом — реальный read-only collector и доверенная доставка его snapshot в полный профиль, затем recovery/network/standalone packaging. Optional monitor без collector не закрывает production admission. Full-GPU timings, source gaps и quality gates прежние; no actuation. Старые batch/registry/UI не переключены, этапы 3–4 не начаты. Mac 8000=200, 8765 закрыт; Worker services/auto clocks не менялись, Ollama/Frigate exited/restart=no.
Этап 1 завершён; этап 2 продолжается. Новый common runtime отделяет recoverable input/readiness от resident lease и умеет требовать свежую epoch без старого backlog. Реальный CPU decoder сохранил PID и BGR на трёх эпохах с двумя обрывами; GPU-модели и настоящий temporal/TGS reset этой проверкой не охвачены. Следом — интеграция восстановления в полный профиль и последовательный full-graph fault probe, затем trusted collector/control plane, network/standalone packaging. Это не переключение существующего full PilotController или продукта. Full-GPU timings, source gaps и quality gates прежние; no actuation. Старые batch/registry/UI не переключены, этапы 3–4 не начаты. Mac 8000=200, 8765 закрыт; Worker services/auto clocks не менялись, Ollama/Frigate exited/restart=no.
После этапа 4 здесь будут перечислены digest самостоятельного полного образа, измеренные статусы и ошибки по recordings, реально проверенные source/hardware/config комбинации, состояние сохранённого EoMT-варианта и оставшиеся physical-live/quality/vehicle-integration ограничения. Готовый Docker и готовая автономия не отождествляются.
@@ -1,8 +1,9 @@
# ADR 0049 — Stream-first full perception profiles
Date: 2026-09-01; updated 2026-09-02 14:52 MSK. Status: stage-1 engineering
baseline complete; stage-2 binary graph and controller-readiness primitives,
not a product runtime cutover or a connected production inventory collector.
Date: 2026-09-01; updated 2026-09-02 15:30 MSK. Status: stage-1 engineering
baseline complete; stage-2 binary graph, readiness and resumable-input primitives.
Full-graph recovery adapter, production inventory collector and product cutover
are not implemented by the latest CPU-only continuity proof.
Execution order remains the four stages in
[the ExecPlan](../OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md).
@@ -101,6 +102,77 @@ explicit byte bound is required. No duplicate new scanner feed is introduced.
## Time and lifecycle
Owner clarification and stage-2 continuity increment, 2026-09-02 15:30
(`c31c46c`): temporary input/network loss must not unload the resident models.
Unknown/stale GPU telemetry is not proof of a competing owner. The desired
response is waiting and resynchronization; verified owner conflict, actual
local lease loss, child/model/decoder failure and explicit cancellation remain
terminal. This supersedes the blanket terminal-readiness TARGET below; previous
terminal fault probes are retained as historical evidence of their opt-in mode.
Two lifetimes are explicit. The resident activation keeps its original
`StreamStart`, local Worker lease and lease generation. Reconnecting input gets
a new `StreamStart.epoch_id`, bound by existing wire v2 on every packet/result;
acquisition session/generation remains independently checked. A network/GCS
heartbeat is not the local ownership heartbeat. The trusted resident controller
continues renewing its own lease while the input waits. No second profile may
claim the GPU during that wait, and telemetry alone cannot renew/release a lease.
`StreamingLifecycle(recover_input=True, source_clock_ns=...)` requires a trusted
source-to-local-clock mapping and, if monitoring is configured, a
`WorkerReadinessMonitor(recoverable=True)`. Both choices belong in the sealed
effective config. Their defaults preserve the historical one-shot diagnostic;
the current full PilotController/BinaryGraphBridge has not been switched. This
compatibility default is not the final product's desired outage policy.
The input phases are active, waiting and synchronizing. Resident GraphState may
remain RUNNING while input is waiting; that means the processes remain loaded,
not that results or actuation are ready. EOF without End, an IPC read deadline,
connection loss or a declared/source-sequence gap pauses the enabled adapter.
Pending input is discarded; active borrowed buffers remain owned until their
callback drains, and its old result cannot pass the epoch/phase gate. A new
connection waits for the old receiver, active callbacks and mailbox-owned work
to drain. No unbounded queue, replay catch-up, future evidence or new model
process is introduced. Explicit End terminates the source; Cancel remains a
real cancellation. Malformed data and actual decoder failure are not relabelled
as a recoverable transport outage. External network error handling remains an
unqualified adapter boundary, not proved by the IPC socket tests.
Resume requires a new init and a successfully decoded random-access H.264 frame,
fresh pose/points from the new epoch, and a temporal-state reset. The measured
decoder resets codec references/DTS inside the same child process; sensor-window
reset retains its bounded allocation but clears rolling state. `ResumeEvidence`
must be derived by the trusted profile adapter, not accepted as a client Boolean.
Every timestamp is at/after reconnect cutoff and no later than the camera;
camera age ≤250 ms, pose/newest-points age ≤100 ms, oldest-points age ≤250 ms and
pose/points skew ≤100 ms. The lifecycle rechecks evidence after reset and cannot
resume if another pause arrived meanwhile. Full graph tracking/motion/TGS/costmap
reset and CPU-consumer old-result disposal are required next, not yet proved by
the diagnostic callback. Replay source time must keep advancing at 1× through
the outage; the CPU fixture proves this only with a synthetic tick source.
Recoverable readiness maps expired/missing inventory, incomplete warmup and
strict-envelope performance unavailability to waiting, not process destruction.
Fresh facts permit beginning resynchronization, not automatic reuse of the old
epoch. Confirmed wrong owner/generation/worker/image/config, known competing GPU
clients and invalid trusted clock/snapshot ordering still fence the activation.
Labelled performance experiments keep their recorded violations and remain
unqualified. The runtime does not manipulate GPU clocks, other services or a
vehicle. Eventual onboard stop/hold, stale-command rejection and motion-resume
policy are independent future safety gates; restored inference is not permission
to move, and GCS heartbeat is not proof of fresh perception.
375 focused tests pass, including repeated reconnects, stale input/results,
pause during reset, telemetry recovery and retained hard-fault fencing. Worker
CPU-only proof: three epochs, 150-ms and 2.2-s outages, unchanged decoder/sentinel
PIDs, identical BGR 3/3, peak input 5,275,461 bytes and complete cleanup. It uses
one real H.264 fragment and synthetic timestamps/pose/points; the sentinel is not
a GPU model, and temporal reset is a diagnostic fixture. No full-graph recovery,
new GPU latency, real inventory collector, external network or standalone-image
qualification follows. Evidence: 85 artifacts, 73 verified code hashes;
`.runtime/perception-stage2-continuity-worker-20260902T1518MSK/manifest.json`,
SHA-256 `fbd327d129c88caa13b7183b1ae2c4767e877a6f5472c0f430875cfd7401ed46`.
Stage-2 controller-readiness increment, 2026-09-02 14:52 (`92625bf`):
`WorkerReadinessMonitor` consumes existing `WorkerOperatingEnvelope` and
`WorkerSnapshot` under the same lifecycle lock as admission. No host I/O occurs