diff --git a/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md b/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md index 1030706..b1c9bcc 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 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.676–63.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.676–63.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 и готовая автономия не отождествляются. diff --git a/docs/adr/0049-stream-first-perception-profiles.md b/docs/adr/0049-stream-first-perception-profiles.md index 0d04e7e..24f6836 100644 --- a/docs/adr/0049-stream-first-perception-profiles.md +++ b/docs/adr/0049-stream-first-perception-profiles.md @@ -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 diff --git a/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md index e045458..9469569 100644 --- a/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md +++ b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md @@ -1936,3 +1936,99 @@ disabled. Optional primitive не засчитывается за готовый 125-ms PASS, auto-clock FAIL, 52 source gaps и quality limits не изменены. Full-source transfer не возвращён, модели/пороги/TTL/CPU-GPU schedule прежние. Этап 2 не закрыт, этапы 3–4 не начаты; registry/UI не переключены, actuation=false. + +## 2026-09-02 15:30 МСК — этап 2, инкремент 8: resident runtime и восстановление входа + +**Результат:** по уточнению владельца transient input/telemetry loss отделён от +аварии всего профиля. Новый явно включаемый common-runtime режим умеет ждать, +сохраняя local lease и процессы, затем принимать новую input epoch. При этом +полный DDRNet/RF-DETR/geometry/TGS pilot ещё не подключён к этому режиму; +нынешний результат — primitives + проверка настоящего CPU H.264 decoder. + +Код `c31c46c`: `streaming_continuity.py`, lifecycle/readiness/ingress/scheduler, +decoder RPC reset, causal sensor-window reset и focused tests. Один resident +StreamStart/lease generation сохраняется; новая input epoch меняет только +входную идентичность и проверяется уже существующим wire v2. Исходный acquisition +session/generation не подменяется. Модели не получают новой startup-команды. + +`recover_input=True` требует доверенный mapped source clock; с readiness нужен +`recoverable=True`. Эти параметры должны войти в effective configuration. +Исторические one-shot diagnostics сохраняют прежний default; включение флага +без настоящего reset/resume adapter не считается миграцией full profile. + +### Пауза, свежесть и настоящая авария + +- EOF без End, IPC deadline, обрыв соединения, source/sequence gap переводят + вход в waiting. Pending input удаляется; active borrowed buffers остаются + зарезервированы до возврата callback. Старые packets/results не пройдут gate. + Serial GPU stage умеет отбросить obsolete работу и продолжить ждать. +- Новая epoch ждёт завершения старого receiver и active/queued work. Decoder + сбрасывает codec/DTS references внутри прежнего PID; causal sensor window + очищает историю, сохраняя фиксированный memory budget. Возобновление требует + fresh decoded keyframe, pose/points не старее reconnect cutoff и успешного + temporal reset; evidence повторно проверяется после reset. Возникшая в это + время новая пауза не может быть затёрта окончанием старого reset. +- Временная потеря/неполнота GPU facts или strict performance envelope вызывает + ожидание, не освобождение ownership. Fresh telemetry сама не возобновляет + старую epoch. Worker-local lease renewals независимы от GCS/входной сети. +- Подтверждённый wrong owner/generation/image/config/worker, competing GPU client, + нарушенный trusted clock contract, настоящая утрата local lease, child/decoder + failure и cancel остаются terminal. Отсутствие данных от K1 само по себе ещё + не доказывает смерть сканера. Управление ровером и его onboard stop/hold, + stale-command rejection и resume policy здесь не реализованы. + +### Worker CPU-only proof + +Session `perception-stage2-continuity-worker-20260902T1518MSK`, фактический запуск +12:18:37 UTC / 15:18:37 МСК. Один временный `ndc-perception-continuity-cpu-probe`: +прежний pinned image, runc, network none, read-only code, 2 CPU / 768 MiB, +pids64, tmpfs256MiB, **без GPU devices и моделей**. Существующие PyAV18/NumPy +подключены read-only; model assets не монтируются, образ не пересобирается. + +Прочитана одна ограниченная строка camera index, init и один существующий H.264 +fragment. Он декодируется три раза, каждый раз с новым синтетическим current +timestamp и synthetic pose/одной точкой. Source counter тикает через каждые +50 ms независимо от входной связи. Это не полный replay реальной записи, +не DDRNet inference, не настоящий JointGraph temporal/TGS reset и не TCP тест. + +| Проверка | Фактический результат | +| --- | --- | +| Input epochs | 3, lease generation 1 сохранена | +| Обрывы IPC | 150 ms и 2.2 s, оба waiting → resync | +| Source ticks во время обрыва | 3 и 44; никакой догоняющей очереди | +| Resident процессы | PID 10/11 неизменны: CPU sentinel и настоящий decoder | +| Decoded BGR | 3/3 одинаковы, SHA-256 `051a6087d897b91b63163975d92b78501cdd98b4c227f7683f05946cd434da37` | +| Local heartbeat | 54 renewals; пауза 2.2 s длиннее lease TTL 2 s не убила профиль | +| Peak input / final input | 5,275,461 / 0 bytes | +| Завершение | Explicit End; children=0, lease released, temporary container removed | + +Тесты отдельно проверяют повторные EOF/idle/incomplete/gap циклы, ограничение +числа threads, stale input/result, pause during reset, reset failure, soft +telemetry recovery, hard conflict и настоящий lease expiry. 375 focused tests +PASS (4.15 s), Ruff/format 14 changed files PASS, mypy 7 modules PASS. Только +прежнее Starlette/httpx предупреждение. Нет моделей/load/full build на Mac; +canonical 8000=200, 8765 закрыт. + +Worker before/after: service IDs/StartedAt/restart counts совпали, Triton ready +200, Ollama/Frigate exited/restart=no. GPU P8, 0%, 210/405 MHz, power limit450 W, +980→985 MiB. Это read-only preservation snapshots, не continuous collector и +не доказательство exclusive GPU readiness. У трёх legacy agents уже были +restart counts43/4/5; их известная проблема не исправлялась и не скрывается. +Настройки services/clocks/quotas не менялись, старые evidence/recordings/weights +сохранены. Удалены только временные CPU container и fixture lease directory. + +Evidence `.runtime/perception-stage2-continuity-worker-20260902T1518MSK/manifest.json`: +85 artifacts, SHA-256 +`fbd327d129c88caa13b7183b1ae2c4767e877a6f5472c0f430875cfd7401ed46`. +73 code hashes сверены между preregistered snapshot, Worker и текущим commit. +Сохранены исходный manifest, commands, report, before/after/cleanup, analysis, +dependency evidence hashes; sealed manifest/analysis скопированы на Worker. + +**Далее в том же этапе 2:** перевести полный PilotController/BinaryGraphBridge +и output consumer на pause/resume, реализовать действительный reset tracking, +motion, rolling geometry/TGS/costmap и провести последовательный full-graph +fault probe с сохранением модельных PID. Затем настоящий trusted collector, +control/network boundary и самостоятельная упаковка. Старый terminal-readiness +TARGET предыдущего инкремента уточнён, но его историческое evidence не переписано. +GPU latency заново не измерялась: conditional PASS / auto-clock FAIL и source +gaps остаются прежними. Этап 2 не закрыт; этапы 3–4 не начаты, actuation=false.