Files
temp/docs/adr/ADR-039-container-resource-types.md
T
freemo e28f9a8597 Docs: Add resource DAG operational semantics, tool reachability, cross-mechanism coordination, container, and LSP resource type ADRs (036-040)
- ADR-036: Resource DAG Operational Semantics (10 purposes, sandbox boundary algebra)
- ADR-037: Tool Reachability and Access Projection (transitive reach, read/write routing)
- ADR-038: Cross-Mechanism Sandbox Coordination (coherence, write-then-sync, lazy materialization)
- ADR-039: Container and Execution Environment Resource Types (9 engine-agnostic types)
- ADR-040: Language Server Protocol Resource Types (lsp-server, lsp-workspace, lsp-document)
- Updated specification.md with 7 new subsections for operational semantics
- Updated resource_dag.md reference doc with operational semantics section
- Updated ADR-008, ADR-011, ADR-015, ADR-027 with cross-references
- Resolved merge conflicts from cherry-pick renumbering (033-037 -> 036-040)
- Fixed all stale display-text references across all files
2026-02-21 19:51:28 -05:00

18 KiB

ADR-039: Container and Execution Environment Resource Types

Status: Accepted
Date: 2026-02-21
Supersedes: None
Author(s): Jeffrey Phillips Freeman Jeffrey.Freeman@CleverThis.com
Approver(s): Jeffrey Phillips Freeman Jeffrey.Freeman@CleverThis.com

Context

CleverAgents operates on diverse resources — git repositories, filesystems, databases, APIs — but the current 24 built-in resource types do not model containerized environments. Modern development workflows depend heavily on containers for reproducible builds, isolated tool execution, and consistent development environments. Tools, LSP servers, and other executables may be available only inside specific containers. The system needs resource types that represent container engines, images, instances, mounts, volumes, and execution environments so that the resource DAG can reason about tool availability, sandbox coordination across host and container boundaries, and equivalence between host files and container-mounted files.

These types must be engine-agnostic — representing containers abstractly regardless of whether the underlying engine is Docker, Podman, containerd, LXC/LXD, CRI-O, or another runtime.

Decision

CleverAgents adds seven new built-in physical resource types for modeling containerized environments, plus one type for executable discovery. These types integrate into the existing resource DAG with containment edges, virtual equivalence links (for files accessible through both host and container), and reference edges (for tool/executable dependencies).

Design

New Resource Types

Container Layer (7 types)

container-runtime

The container engine installation — a running daemon or CLI tool that manages containers.

Field Value
Kind physical
Sandbox strategy none
User-addable yes
CLI arguments --engine-type (required: docker, podman, containerd, lxc, lxd, cri-o, other), --socket-path (optional), --endpoint (optional), --version (optional)
Allowed parents (none — top-level resource)
Allowed children container-image (0..*), container-instance (0..*), container-volume (0..*), container-network (0..*)
Auto-discovery Discovers running instances, pulled images, created volumes, and configured networks from the engine
Capabilities read: true, write: false, sandbox: false, checkpoint: false

Properties: engine_type (docker | podman | containerd | lxc | lxd | cri-o | other), socket_path or endpoint, version, api_version.

container-image

An immutable container image (OCI image, LXC image, etc.).

Field Value
Kind physical
Sandbox strategy none (images are immutable)
User-addable yes
CLI arguments --image-ref (required, e.g., python:3.12-slim), --digest (optional), --engine-type (optional, inherited from parent runtime)
Allowed parents container-runtime (1)
Allowed children container-instance (0..*, instances created from this image)
Auto-discovery Discovered from container-runtime. Does not auto-discover children (instances are discovered from the runtime).
Capabilities read: true, write: false, sandbox: false, checkpoint: false

Properties: image_ref, digest, engine_type, architecture, os, size_bytes, created_at, labels (key-value).

container-instance

A container — running, stopped, paused, or created.

Field Value
Kind physical
Sandbox strategy snapshot
User-addable yes
CLI arguments --container-id (optional), --name (optional), --image-ref (optional, links to parent image), --engine-type (optional, inherited from parent runtime)
Allowed parents container-runtime (1), container-image (0..1, the image it was created from)
Allowed children container-mount (0..*), container-exec-env (1), container-port (0..*)
Auto-discovery Discovered from container-runtime. Auto-discovers mounts, execution environment, and port mappings.
Capabilities read: true, write: true, sandbox: true, checkpoint: true

Properties: container_id, name, state (running | stopped | paused | created | restarting | removing | dead), image_ref, engine_type, pid, created_at, labels (key-value), hostname, working_dir.

The snapshot sandbox strategy for container instances creates a container checkpoint or commit (engine-dependent), allowing rollback to a known state. For Docker/Podman this uses docker commit or docker checkpoint; for LXC/LXD this uses LXD snapshots.

container-mount

A mount point mapping external storage into a container.

Field Value
Kind physical
Sandbox strategy (inherits from container-instance parent)
User-addable no (auto-discovered from container-instance)
Allowed parents container-instance (1)
Allowed children fs-directory (0..1, the mounted content root), fs-file (0..*, if a single file is mounted)
Auto-discovery Discovered from container-instance by inspecting container mount configuration. Auto-discovers the mounted filesystem contents as fs-directory / fs-file children.
Capabilities read: true, write: (depends on mount read_only flag), sandbox: (inherits), checkpoint: (inherits)

Properties: source (host path, volume name, or tmpfs), target (container-internal path), mount_type (bind | volume | tmpfs | npipe), read_only, propagation (rprivate | private | rshared | shared | rslave | slave).

Virtual equivalence: When mount_type is bind, the fs-directory or fs-file children inside the container are equivalent to the corresponding fs-directory or fs-file resources on the host. They share the same directory or file virtual parent. The coherence property on this equivalence link is transparent — changes on either side are immediately visible to the other because they share the same underlying storage.

When mount_type is volume, the filesystem contents are independent of the host filesystem (unless the volume is backed by a host directory, in which case it behaves like a bind mount). Coherence: independent by default, transparent if the volume driver provides pass-through semantics.

container-volume

A named volume managed by the container engine.

Field Value
Kind physical
Sandbox strategy snapshot
User-addable yes
CLI arguments --volume-name (required), --driver (optional, default: local), --engine-type (optional, inherited from parent runtime)
Allowed parents container-runtime (1)
Allowed children fs-directory (0..1, root of volume contents)
Auto-discovery Discovered from container-runtime. Auto-discovers the root directory of the volume.
Capabilities read: true, write: true, sandbox: true, checkpoint: true

Properties: volume_name, driver, mount_point (host path where volume data is stored), engine_type, labels (key-value), scope (local | global).

container-exec-env

The execution environment inside a container — what is available to run.

Field Value
Kind physical
Sandbox strategy (inherits from container-instance parent)
User-addable no (auto-discovered from container-instance)
Allowed parents container-instance (1)
Allowed children executable (0..*)
Auto-discovery Discovered from container-instance. Auto-discovers executables by scanning the container's PATH directories.
Capabilities read: true, write: false, sandbox: (inherits), checkpoint: (inherits)

Properties: path_dirs (list of PATH entries), env_vars (key-value environment variables), shell (default shell path), os (linux | windows | macos), architecture (amd64 | arm64 | ...), user (default user), working_dir.

This resource type answers the question: "What can I run in this container?" It is the foundation for tool and LSP server dependency resolution — by discovering what executables are available, the system can determine whether a particular tool or LSP server can run inside a given container.

container-network

A container network configuration.

Field Value
Kind physical
Sandbox strategy none
User-addable no (auto-discovered from container-runtime)
Allowed parents container-runtime (1)
Allowed children (none)
Auto-discovery Discovered from container-runtime.
Capabilities read: true, write: false, sandbox: false, checkpoint: false

Properties: network_name, driver (bridge | host | overlay | macvlan | none), subnet, gateway, scope (local | swarm | global).

container-port

A port mapping exposing a container port to the host.

Field Value
Kind physical
Sandbox strategy (inherits from container-instance parent)
User-addable no (auto-discovered from container-instance)
Allowed parents container-instance (1)
Allowed children (none)
Auto-discovery Discovered from container-instance.
Capabilities read: true, write: false, sandbox: (inherits), checkpoint: (inherits)

Properties: container_port, host_port, host_ip, protocol (tcp | udp | sctp).

Execution Environment Layer (1 type)

executable

A binary, script, or interpreter available in some execution environment.

Field Value
Kind physical
Sandbox strategy none (executables themselves are not sandboxed; the environment they run in is)
User-addable yes
CLI arguments --path (required, path to the executable), --name (optional, defaults to filename), --version (optional)
Allowed parents container-exec-env (0..1, if inside a container), fs-directory (0..1, if on host filesystem)
Allowed children (none)
Auto-discovery Discovered from container-exec-env (scanning container PATH) or from fs-directory (scanning host PATH).
Capabilities read: true, write: false, sandbox: false, checkpoint: false

Properties: path (absolute path within the execution environment), name (the executable name, e.g., node, python3, pylsp), version (if detectable), interpreter (for scripts: python, bash, node, etc.), content_hash (SHA-256 of the binary).

Virtual equivalence: The same executable installed in multiple locations (host, multiple containers) can share a file virtual parent when the content hash matches. This enables the query: "Where else is this executable available?"

Tool dependency relationship: Tools and LSP servers declare dependencies on executables via references edges. A tool that requires node v18+ has a references edge to the executable resource for node. The system can then query: "Which container-exec-env or host fs-directory contains a node executable matching the version constraint?"

Containment Hierarchy Summary

container-runtime (docker/podman/containerd/lxc/lxd/cri-o)
  ├── container-image
  │     └── (instances created from this image link back)
  ├── container-instance
  │     ├── container-mount
  │     │     ├── fs-directory  ──[virtual equivalence]──▷ directory (virtual)
  │     │     └── fs-file       ──[virtual equivalence]──▷ file (virtual)
  │     ├── container-exec-env
  │     │     └── executable    ──[virtual equivalence]──▷ file (virtual)
  │     └── container-port
  ├── container-volume
  │     └── fs-directory
  └── container-network

Sandbox Domain Impact

Container resource types create new sandbox domains in the DAG:

Sandbox Boundary Strategy Domain Contents
container-instance snapshot All mounts, exec-env, ports, and their descendants within the container
container-volume snapshot The volume's filesystem contents

These domains are separate from host filesystem sandbox domains. When a bind mount creates virtual equivalence between container files and host files, the files exist in two different sandbox domains simultaneously. This is the primary use case for the cross-mechanism coordination protocol defined in ADR-038.

Engine-Specific Behavior

The container-runtime handler dispatches to engine-specific sub-handlers based on engine_type:

Engine Discovery Instance Management Snapshot Mechanism
Docker Docker Engine API / docker CLI docker inspect, docker ps docker commit, docker checkpoint (experimental)
Podman Podman API / podman CLI podman inspect, podman ps podman commit, podman container checkpoint
containerd containerd API / ctr CLI ctr containers list ctr snapshots
LXC/LXD LXD REST API / lxc CLI lxc list, lxc info lxc snapshot
CRI-O CRI gRPC API crictl ps, crictl inspect Engine-dependent

The engine-specific details are encapsulated in the resource handler — the rest of the system interacts with the engine-agnostic resource types.

Constraints

  • All container resource types must work with any engine type. Engine-specific behavior is encapsulated in the handler, not exposed in the resource type or DAG structure.
  • container-exec-env auto-discovery (scanning PATH for executables) may be expensive for containers with large PATH directories. Discovery should be lazy (triggered on demand or when a tool dependency needs resolution) rather than eager.
  • container-mount equivalence with host files requires the system to resolve bind mount source paths to registered host resources. If the host directory is not registered as a resource, no equivalence link is created.
  • container-instance snapshot sandbox strategy depends on engine support. Not all engines support checkpointing (e.g., Docker checkpoint is experimental). When checkpointing is unavailable, the system falls back to none strategy with a warning.

Consequences

Positive

  • Container environments become first-class citizens in the resource DAG, enabling tool dependency resolution, sandbox coordination, and equivalence tracking across host and container boundaries.
  • Engine-agnostic types ensure the system works with Docker, Podman, LXC/LXD, and any future container runtime without structural changes.
  • The executable type enables answering "where can I run this tool?" — a critical question for heterogeneous environments.

Negative

  • Nine new resource types (including container-port and container-network) add complexity to the type registry and documentation.
  • Container discovery requires engine-specific handler implementations for each supported engine.
  • Executable discovery (scanning PATH) adds overhead and may produce large numbers of auto-discovered resources.

Risks

  • Container state is volatile — instances can be stopped/removed externally without the system knowing. Resource staleness detection and cleanup are critical.
  • Bind mount detection requires inspecting container configuration, which may require elevated privileges or engine API access.
  • Snapshot-based sandboxing for containers may be slow for large container filesystems.

Alternatives Considered

Docker-only resource types — Simpler but locks the system to one engine. The container ecosystem has multiple viable engines, and users working with Podman, LXC/LXD, or containerd would be excluded.

No container resource types (external tool management only) — Treats containers as opaque external environments. Tools running in containers would be modeled as MCP servers with no visibility into the container's internals. This prevents tool dependency resolution and cross-mechanism equivalence tracking.

Compliance

  • Type registration tests: Each new resource type validates correctly (CLI args, parent/child constraints, capabilities).
  • Auto-discovery tests: Container runtime discovery correctly identifies instances, images, volumes, networks for at least Docker and Podman.
  • Mount equivalence tests: Bind mount files correctly link to host files through virtual parents with transparent coherence.
  • Executable discovery tests: Container exec-env scanning correctly identifies executables and links them to file virtual parents when content hashes match host executables.
  • Engine abstraction tests: The same test suite runs against Docker and Podman handlers to verify engine-agnostic behavior.
ADR Title Relationship
ADR-008 Resource System These types extend the built-in resource type registry
ADR-036 Resource DAG Operational Semantics Container types create new sandbox domains subject to the sandbox boundary algebra
ADR-038 Cross-Mechanism Sandbox Coordination Container/host equivalence is the primary use case for cross-mechanism coordination
ADR-040 LSP Resource Types LSP servers may run inside containers, referencing container executables

Acceptance

Votes For

Voter Comment
Jeffrey Phillips Freeman Jeffrey.Freeman@CleverThis.com Engine-agnostic container types with executable discovery enable tool dependency resolution and cross-mechanism coordination

Total: 1

Votes Against

Voter Comment

Total: 0

Abstentions

Voter Comment

Total: 0