# ADR 0051 — Modular AI containers and composed Observatory profiles Date: 2026-09-03. Owner-approved target; the first local modular vertical slice is installed. ## Decision and supersession A reusable module is an independently packaged Docker image for a model or a cohesive algorithmic function. A profile is an immutable, validated composition of module versions, parameters, input/output connections and execution policy. A LAB run applies that composition to an exact recording snapshot. A new combination does not require building another image containing all models. This replaces the earlier **one full profile = one image/container** packaging requirement in the historical plan. It keeps ADR 0050's recorded-first purpose, ADR 0048's generic installed-package boundary and the stream contracts from ADR 0049. Several containers are not intrinsically a defect. Per-LAB application forks, hidden host dependencies and duplicated data preparation remain defects. The future onboard host is CUDA-capable, architecture/runtime compatible hardware. It is explicitly **not Mac Mini**. Exact CPU architecture, GPU, driver and inference-runtime compatibility still need target qualification; CUDA availability alone is not a promise that every existing image will run. New owned module images/containers use the `ndc-` namespace, readable model or function names, explicit versions and ownership labels. A composition has its own readable LAB label; module/composition/job identities are linked in runtime metadata. A reused module need not be renamed to match every LAB that uses it. ## Operator composition Each recording exposes AI-layer settings inside the existing Observatory. Use functional groups with a single-choice Select, not a checklist of arbitrary containers. Segmentation admits **at most one** provider: DDRNet or EoMT, never both in the same new LAB. Optional groups may offer None if the resulting graph still satisfies its declared outputs. A geometry-only or segmentation-only LAB is valid and must not claim the omitted capabilities. Candidate groups are segmentation, object detection, LiDAR/TGS geometry and costmap, object/range association, motion and policy-shadow. Their final physical module boundaries follow existing code ownership and measured data exchange, not a mandatory container per mathematical operation. Multiple capabilities provided by one module do not instantiate that module multiple times. The server validates provider cardinality, dependencies, source capabilities, calibration/time frames, output contracts and installed Worker versions. A client cannot supply executable argv, image names, host paths or arbitrary resource settings. Invalid dependencies are explained, never silently supplemented by old LAB overlays or an unselected second segmenter. An exact existing published composition is opened, not recomputed. The settings remain editable so the operator can create another composition. There is no Calculate action for a complete exact cache hit, no “calculation complete” button/badge, and no duplicate LAB. The grouped selectors keep already-used providers: completion belongs to the whole composition, not to an individual dropdown option. This supersedes the old finite-profile selector grammar, not its exact-cache and idempotency guarantees. ## Execution, identity and caches - Keep one recorded owner on Worker006 and serialize heavy GPU execution. Selecting several modules does not authorize concurrent GPU model jobs. - Share source delivery/preparation locally on Worker. Intermediate image/point buffers do not round-trip through Core between modules. Do not reintroduce whole-recording upload/decode as a permanent streaming-start prerequisite. - Keep a common timestamped, bounded I/O contract with explicit sensor gaps, coordinate frames, unavailable outputs and causal temporal state. Recorded analysis may be slower than acquisition; live has separate freshness gates. - Freeze graph topology, module image/weights/code/config identities, input identities, preprocessing, calibration, cadence, precision and state policy. Canonical ordering of the selection UI is not part of the semantic identity. - Reuse a node only for exact validated inputs and producer identity. A changed detector invalidates its dependent range/motion results, not an independent segmentation result. Stateful reuse also binds initialization and history. - Final LAB/cache publication remains on Core. Worker source/preparation caches are not the final viewer store. Failed publication retries the sealed result, not inference. A partially cached graph is not a complete ready LAB. - Record reused versus computed nodes and provenance. Cache playback or cached composition assembly is never reported as measured onboard processing FPS. Onboard modules are long-lived within a mission; do not start a container or reload weights per frame. Resident memory, local transport, bounded queues and end-to-end latency require a joint benchmark. An optional later co-location of hot nodes is a measured deployment optimization, not a reason to remove logical modularity. No automatic actuation or navigation acceptance is introduced. ## Current implementation and migration Current M49 runs CPU TGS in its specialized agent. Current LAB V1 is an installed fixed stack: prepare → EoMT → DDRNet → assemble, with host-bound model/runtime assets. Neither is the new modular composition system. Keep the successful M49 publication and exact existing releases; retain old dual-segmentation results as historical comparisons, without admitting that combination in new profiles. Reuse `InstalledLabPackage`, its generic launcher, queue/claim/recovery, source CAS, verified publication and common viewer. Extend the versioned contracts for compositions and per-node reuse. Do not redesign the queue or create another agent per model. Source CAS alone does not implement intermediate-result reuse. The owner authorized Worker cleanup. Classify every exact container/image/cache against running services, pinned packages, model assets, rollback and retained evidence before deleting. Stopped instances can be retired independently of images and volumes. Preserve raw recordings, published LABs, Legacy views, required source/model caches and one usable rollback; no global Docker prune. The accepted EoMT disk floor is now **250 GiB plus its working-set estimate**. Source and narrow tests have changed; installed EoMT still has 350 GiB until a new sealed image/release is activated. Never patch a historical digest in place. ## Acceptance and route Done means: select one provider per group; compute two distinct compositions on compatible recordings with exact cache reuse; view their complete bound outputs from Core; recover publication without compute; prove exclusive GPU scheduling and cleanup; cold-start the selected module distribution without developer checkout or unlisted caches. Onboard qualification remains future work. The historical combined route remains documented in [the four-stage ExecPlan](../OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md). ## Local implementation record — 2026-09-03 The first implemented slice replaces the Observatory's fixed profile selector and separate refresh/calculate controls with one always-available `Сконфигурировать AI-слой` action for the selected source. Its canonical Window contains functional groups, one provider Select per group, the close action and one `Рассчитать` action. The Window uses background, spacing and typography for grouping; it has no group outlines, header divider lines or modal rim. DDRNet and EoMT are independent alternatives in the Segmentation group. They share only the model-neutral `camera-source` preparation step and neither model consumes the other model's result. The installed module repositories and exact local image identities are: - `ndc/mission-core-ai-module-camera-source` — `da926459aee0a841bbdfaf80a0eb5fbead354c56794d1f3384eeba66d0a49e00`; - `ndc/mission-core-ai-module-ddrnet` — `489fc7d1157fd0f1cd1d82e06a15737b7b2aaaf72b2ddb2aca2992b91a97488e`; - `ndc/mission-core-ai-module-eomt` — `5b770178e4a5c8fbe8f8ddab3b83a598973dbe103b669851110b11a0918ab846`; - `ndc/mission-core-ai-module-rf-detr` — `2b8b44be8e9ee4060aa6997fc4c025ad7120f37ecd720a9e59b5e02ac6c90f66`; - `ndc/mission-core-ai-module-object-distance` — `69d68f64981b41e5bcce1e642433e3d466b88c51942a5ba3aec9180d8ed04263`; - `ndc/mission-core-ai-module-tgs` — `f9278ab21aa65045be993dd19bffc25f49955e19598893ac78cc4761ca63ecf3`. The executable graph also contains `ai-detection-rf-detr-v1` for image-space boxes and `ai-range-object-distance-v1` for box-to-LiDAR association. The range package executes RF-DETR as its explicit dependency, then uses synchronized LiDAR, pose and calibration to estimate range. TGS consumes LiDAR, pose and its own history independently. Selecting TGS and range therefore produces two independent durable jobs; segmentation does not feed either of them. The common Worker agent launches package steps with job-specific container names under `ndc-mission-core-ai-module-*`, serializes GPU work, publishes a `missioncore.recorded-ai-layer-review/v1` result and leaves the historical combined LAB V1 and Legacy contour intact. Submission creates a durable Observatory job immediately. The source-bound evidence area shows its selected configuration, current phase, measured progress and an estimated remaining time. A published result moves into the existing evidence list and uses the same open, rename and delete actions as the other portable LAB results. The active Worker 006 directory release is `20260903-v5`, release SHA-256 `a87c82adfa1058f14f850f488ace38e5c7c9d9e2145d4678a81b52f2a1aad573`. Its common agent image SHA-256 is `d6f2ef1a3f38ebc8503b62296ca9def10472a60a41ffc5edd123df565520dec8`. The DDRNet, EoMT, RF-DETR and object-distance definition SHA-256 values are respectively `b04206a8472588fee22e0282228e51b7817c80f9739180e834b704733d7aaf76`, `6d13402883e8fa79a8ea97b15e81e704d3c0f9dac5d94445e5e53c18dcebe98f`, `a89f51a66a070deb50f4904f596545cdcd7289df7e42b8511aec9547dedd52e8` and `cc56e72fdfb38565a0b402c90a91917821463d980f5855e4cdf4d8b9f262a94c`. The standalone detector and composite range package have distinct resource profile identities, so their otherwise shared RF-DETR model manifest cannot collapse into one executor registration. All four package executor identities are unique. DDRNet, EoMT, RF-DETR and object-distance pass live source, executor, sealed-definition and durable-queue preflight for `20260828T130511Z_viewer_live`; the published M49 TGS result is an exact cache hit. No new full-recording RF-DETR or object-distance inference was run as part of this installation acceptance.