9.3 KiB
ADR 0050 — Recorded Observatory first; portable profiles then onboard
Date: 2026-09-02. Decision accepted by the owner; implementation in progress. This supersedes ADR 0049's realtime-first product gate and execution order, not its live-stream integrity, ownership or safety contracts.
Decision
The primary operator workflow is a complete calculation of a compatible K1 recording with a selected immutable profile, followed by publication and cached review. Processing may be slower than acquisition. Network latency is evidence, not a prerequisite for using the laboratory. After this workflow works, compare Docker configurations; later qualify the selected configuration on actual onboard hardware. No vehicle or remote-realtime acceptance is claimed now.
Keep the existing source admission, queue, artifact store, publication recovery, streaming runtime and common viewer. Do not introduce another per-LAB application. One Worker executes one active profile; alternative profiles remain sequential. M4.9T5 currently supplies CPU TGS; LAB V1 supplies sequential EoMT/DDRNet, not the complete future detector/distance/motion/TGS/policy profile.
Recorded analysis versus realtime rehearsal
Recorded analysis preserves source timestamps and causal ordering, uses bounded backpressure, and accounts for every required scheduled input/result. Its elapsed wall time need not match the source clock. Source sensor gaps remain unknown. Do not disguise live drop/resync as a complete recorded result. Introducing this execution mode requires an explicit versioned contract, not silently weakening the existing 1× live freshness, deadline or ownership gates.
Realtime rehearsal remains an independent qualification. Historical network canaries retain their original FAIL results and thresholds. Neither cached video playback FPS nor end-to-end upload/export time is a Worker compute benchmark. Measure preparation, warmup, processing, delivery and publication separately; onboard estimates are conditional on matching hardware and effective config.
Result identity and UI
Only compatible, not-yet-calculated current profile versions belong in the calculation selector. Published results of every version remain below as evidence. All calculated means no Calculate action, an empty/disabled selector, and Refresh. Refresh, source selection and cached review must never start inference.
Reuse requires the exact admitted source fingerprint and immutable definition (including model, image, configuration, adapter and result-contract identities). An old LAB name, a legacy overlay, or compute success without publication is not a matching cache. Missing/corrupt artifacts must not suppress a valid retry. Publication failure retries publication, not computation, while the sealed package is recoverable. Changed profile versions become new calculations.
First implementation increment
Portable queue admission now opts into an atomic duplicate-computation guard. It uses the existing job identity, not a second cache key ontology, and rejects a different request while the identical job is active, requires reconciliation, or has a sealed result pending/failed publication. The check and INSERT use one SQLite transaction. Exact retries retain the original idempotency semantics. A genuinely failed compute can be retried with a new request key. Legacy queue callers retain their existing policy; no schema migration or Worker/image change is introduced.
Published-cache verification, catalog projection, selector changes, progress and complete recorded-analysis execution are still pending. This increment does not mark stage 1 or the full workflow complete. Tests cover concurrent admission, durability, changed source/profile, failure retry and HTTP 409 duplicate handling.
Second increment: bounded non-binding idle claims
Claim/v3 is active on the backend and both current Worker006 control agents. Idle polls do not persist receipts; actual grants are durable and share the request-ID namespace with preserved v2 history. Repeating a non-binding v3 idle request may later acquire work, unlike an old persisted v2 empty receipt. The 50,000-row legacy ledger remains intact; a separate 50,000-positive-grant budget does not change the shared 128 MiB database/WAL/SHM storage bound.
Only the imported gateway's request schema literal changes in two pinned child images. Compute package identities and model images remain unchanged. The exact control-agent create declarations, separate from executor package declarations, are now the durable runtime source; old agents remain stopped for rollback. 126 focused tests and 16 real empty-capability Worker-to-backend probes passed. All pre-existing queue row hashes are unchanged. This repairs dispatch polling, not published-cache verification or full recorded-workflow acceptance. See the repair evidence and rollback boundary.
Third increment: exact published-result cache (2026-09-03)
Implemented and activated as a matching backend/frontend release on canonical8000 on 2026-09-03 after an owner-approved Docker VM restart recovered memory headroom. Full typecheck,714 frontend tests and production build passed sequentially; API catalogs and in-app UI were checked without creating inference jobs. All queue row hashes are preserved. This does not claim a completed recorded run.
The portable catalog now joins successful published queue receipts to the current per-source catalog snapshot, immutable definition, Session publication binding, calculation profile, package contract, central manifest and every artifact. No matching by LAB name, operator label, or the newest 100-job page. The queue receives two indexes, with no deletion or rewriting of history. The existing computation identity remains the only computation key.
An exact usable result projects existing / open-existing, its result ID and
path-free source/definition/package identities. It disables new submission but
does not require Worker dispatch or raw-source preparation for cached review.
Missing/corrupt artifacts do not count as coverage; the older evidence remains.
The newest verified exact candidate is returned; other versions are not hidden
from the evidence catalog or mistaken for the current calculation.
Large immutable result objects are hashed in 1 MiB chunks on first use or file metadata change. A bounded 4096-entry memo rechecks dev/inode/size/mtime/ctime; normal refresh does not reread unchanged large objects. This is result-integrity IO, not source upload, source decoding, model inference, or an FPS measurement. The queue INSERT fence rechecks the published candidate atomically. It never streams large files while holding the write lock: cold/concurrent/changed verification returns HTTP409 requesting Refresh. Exact idempotency retries still return the original job. Verified corruption permits a new request.
The frontend's existing portable decoder now accepts only bound, internally consistent cached results. No per-LAB page, renderer or selector implementation was introduced. Full selector/progress/product acceptance remains stage 2. Browser QA confirms that source/setup-only job selection can still display a legacy completion status against a current definition. Exact-version status binding and separating archives from executable choices remain required; the activated backend cache does not prove those UI changes complete. See verification and activation status.
Selector contract clarification — 2026-09-03
The owner explicitly excludes completion buttons and status badges. A completed current profile is represented by its reviewable, profile-marked evidence below, not by a “calculation complete” control. The selector now contains compatible portable definitions with no verified exact published cache hit. An archived LAB or old definition never hides a new version. An empty selector has no Calculate. An in-flight computation has only an activity indicator; failed publication keeps a separate recovery action and never starts inference again.
Removed the six-card presentation cap; the existing catalog window limit remains explicit. Queue reads now filter definition SHA before pagination. Hook snapshots are fenced by source/setup/definition so previous jobs cannot flash in the next selection. New synthetic tests exercise none/all/partially cached choices, unavailable executors, legacy/new-version separation and pre-effect selection changes. Sequential validation:720 frontend tests,52 queue/API tests, architecture, typecheck, Ruff/mypy and production build PASS. Full recorded-run/product acceptance and measured progress counters remain stage2. Historical terminal logs do not become a new selection's error. The existing responsive selector layout follows workspace width, including restored narrow windows, rather than only the browser viewport.
Boundaries
No Synology deployment, hardware actuation, motor integration, new capture, silent model substitutions or deletion of recordings/results. A Docker image's portability does not promise that a CUDA build runs unchanged on Apple Silicon. Physical-live and onboard/vehicle acceptance require the actual target hardware.
The only maintained execution plan is the four-stage ExecPlan.