Feature: Devcontainer Activation, Stop and Rebuild As a CleverAgents developer I want devcontainers to be lazily activated and manually stopped or rebuilt So that containers start on demand and can be controlled explicitly # ── Lazy activation ──────────────────────────────────────── Scenario: Lazy activation succeeds on inactive container Given a mock devcontainer CLI runner And the runner configured for successful activation When I activate container "01TESTLIFECYCLE0000000010" at "/workspace/project" Then the container state should be "running" And the container ID should be "aabbccddee0011223344" And the workspace path should be "/workspaces/project" And the runner should have received a devcontainer up call Scenario: Lazy activation transitions to error on failure Given a mock devcontainer CLI runner And the runner configured for failed activation When I attempt to activate container "01TESTLIFECYCLE0000000011" at "/workspace/project" Then the activation should raise RuntimeError And the container state for "01TESTLIFECYCLE0000000011" should be "failed" # ── Manual stop ──────────────────────────────────────────── Scenario: Stop transitions active container to stopped Given a mock devcontainer CLI runner And an active container "01TESTLIFECYCLE0000000020" with container ID "ctr-123" When I stop container "01TESTLIFECYCLE0000000020" Then the container state for "01TESTLIFECYCLE0000000020" should be "stopped" And the runner should have received a docker stop call # ── Rebuild ──────────────────────────────────────────────── Scenario: Rebuild transitions stopped container to active Given a mock devcontainer CLI runner And the runner configured for successful activation And a stopped container "01TESTLIFECYCLE0000000030" When I rebuild container "01TESTLIFECYCLE0000000030" at "/workspace/project" Then the container state for "01TESTLIFECYCLE0000000030" should be "running" Scenario: Rebuild transitions error container to active Given a mock devcontainer CLI runner And the runner configured for successful activation And an errored container "01TESTLIFECYCLE0000000031" When I rebuild container "01TESTLIFECYCLE0000000031" at "/workspace/project" Then the container state for "01TESTLIFECYCLE0000000031" should be "running" # ── Argument validation ──────────────────────────────────── Scenario: Activate rejects empty resource_id When I attempt to activate a container with empty resource_id Then the activation should raise ValueError with "resource_id" Scenario: Activate rejects empty workspace_folder When I attempt to activate a container with empty workspace_folder Then the activation should raise ValueError with "workspace_folder" Scenario: Stop rejects empty resource_id When I attempt to stop a container with empty resource_id Then the stop should raise ValueError with "resource_id" # ── Activate on already-running container ──────────────────── Scenario: Activate on already-running container raises ValueError Given a mock devcontainer CLI runner And the runner configured for successful activation And an active container "01TESTLIFECYCLE0000000140" with container ID "ctr-dup" When I attempt to activate container "01TESTLIFECYCLE0000000140" at "/workspace" Then the activation should raise ValueError with "Invalid lifecycle transition" # ── Stop container with no container_id ───────────────────── Scenario: Stop container with no container_id skips docker stop Given a mock devcontainer CLI runner And an active container with no container_id "01TESTLIFECYCLE0000000150" When I stop container "01TESTLIFECYCLE0000000150" Then the container state for "01TESTLIFECYCLE0000000150" should be "stopped" And the runner should not have received a docker stop call # ── Activation fails when container_id is missing ──────────── Scenario: Activation fails when devcontainer up returns no container_id Given a mock devcontainer CLI runner And the runner configured for activation with no container_id When I attempt to activate container "01TESTLIFECYCLE0000000160" at "/workspace" Then the activation should raise RuntimeError And the container state for "01TESTLIFECYCLE0000000160" should be "failed" # ── Direct rebuild_container coverage ─────────────────────── Scenario: rebuild_container directly stops then reactivates Given a mock devcontainer CLI runner And the runner configured for successful activation And a stopped container "01TESTLIFECYCLE0000000090" When I call rebuild_container for "01TESTLIFECYCLE0000000090" at "/workspace" Then the container state for "01TESTLIFECYCLE0000000090" should be "running" Scenario: rebuild_container rejects empty resource_id When I call rebuild_container with empty resource_id Then the rebuild should raise ValueError with "resource_id" Scenario: rebuild_container rejects empty workspace_folder When I call rebuild_container with empty workspace_folder Then the rebuild should raise ValueError with "workspace_folder" # ── Stop container error path coverage ───────────────────── Scenario: stop_container transitions to error when docker stop raises Given a mock devcontainer CLI runner And the runner configured to raise exception on stop And an active container "01TESTLIFECYCLE0000000110" with container ID "ctr-sf" When I attempt to stop container "01TESTLIFECYCLE0000000110" Then the stop should raise RuntimeError And the container state for "01TESTLIFECYCLE0000000110" should be "failed" # ── Activate generic exception path coverage ─────────────── Scenario: activate_container transitions to error on generic exception Given a mock devcontainer CLI runner And the runner configured to raise generic exception on up When I attempt to activate container "01TESTLIFECYCLE0000000120" at "/workspace" Then the activation should raise RuntimeError And the container state for "01TESTLIFECYCLE0000000120" should be "failed" # ── Stop container non-zero return code (F2) ─────────────── Scenario: stop_container transitions to error when docker stop returns non-zero Given a mock devcontainer CLI runner And the runner configured for failed docker stop And an active container "01TESTLIFECYCLE0000000170" with container ID "ctr-rc1" When I attempt to stop container "01TESTLIFECYCLE0000000170" Then the stop should raise RuntimeError And the container state for "01TESTLIFECYCLE0000000170" should be "failed" # ── R20: workspace_folder path validation ────────────────── Scenario: Activate rejects relative workspace_folder When I attempt to activate a container with relative workspace_folder Then the activation should raise ValueError with "absolute path" # ── S2: Activation timeout transitions to failed ─────────── Scenario: Activation timeout transitions container to failed state Given a mock devcontainer CLI runner that times out And a lifecycle tracker for resource "01TESTLIFECYCLE0000000350" When I attempt to activate the timed-out container Then the activation should raise RuntimeError with "timed out" And the tracker "01TESTLIFECYCLE0000000350" should be in "failed" state # ── F4: Orphaned container cleanup on timeout ────────────── Scenario: Activation timeout attempts to stop orphaned containers Given a mock devcontainer CLI runner that times out with orphan containers And a lifecycle tracker for resource "01TESTLIFECYCLE0000000360" When I attempt to activate the timed-out container with orphan cleanup Then the activation should raise RuntimeError with "timed out" And the runner should have attempted orphan container cleanup # ── F6: R10 fix explicit assertion (container_id clearing) ─ Scenario: Stopped container has container_id cleared Given a mock devcontainer CLI runner And an active container "01TESTLIFECYCLE0000000380" with container ID "ctr-r10" When I stop container "01TESTLIFECYCLE0000000380" Then the container state for "01TESTLIFECYCLE0000000380" should be "stopped" And the container_id for "01TESTLIFECYCLE0000000380" should be None And the workspace_path for "01TESTLIFECYCLE0000000380" should be None Scenario: Failed activation clears container_id Given a mock devcontainer CLI runner And the runner configured for failed activation When I attempt to activate container "01TESTLIFECYCLE0000000381" at "/workspace/project" Then the container state for "01TESTLIFECYCLE0000000381" should be "failed" And the container_id for "01TESTLIFECYCLE0000000381" should be None # ── R8-F2: stop_container early return on terminal state ──── Scenario: stop_container returns early when container already stopped Given a mock devcontainer CLI runner And a stopped container "01TESTLIFECYCLE0000000660" When I stop container "01TESTLIFECYCLE0000000660" expecting early return Then the container state for "01TESTLIFECYCLE0000000660" should be "stopped" And the runner should not have received a docker stop call Scenario: stop_container returns early when container already failed Given a mock devcontainer CLI runner And an errored container "01TESTLIFECYCLE0000000670" When I stop container "01TESTLIFECYCLE0000000670" expecting early return Then the container state for "01TESTLIFECYCLE0000000670" should be "failed" And the runner should not have received a docker stop call # ── F15: host_workspace_path stored on activation ─────────── Scenario: Activation stores host_workspace_path for health probes Given a mock devcontainer CLI runner And the runner configured for successful activation When I activate container "01TESTLIFECYCLE0000000800" at "/workspace/project" Then the container state should be "running" And the host_workspace_path for "01TESTLIFECYCLE0000000800" should be "/workspace/project" # ── F10: rebuild passes --reset-container flag ────────────── Scenario: Rebuild passes --reset-container to devcontainer up Given a mock devcontainer CLI runner And the runner configured for successful activation And a stopped container "01TESTLIFECYCLE0000000810" When I call rebuild_container for "01TESTLIFECYCLE0000000810" at "/workspace/project" Then the container state for "01TESTLIFECYCLE0000000810" should be "running" And the devcontainer up call should include "--reset-container" Scenario: Normal activation does not pass --reset-container Given a mock devcontainer CLI runner And the runner configured for successful activation When I activate container "01TESTLIFECYCLE0000000811" at "/workspace/project" Then the container state should be "running" And the devcontainer up call should not include "--reset-container"