{
  "version": 1,
  "state": "004-containerized-compose-runtime",
  "title": "Containerize the application, then run it with Compose",
  "purpose": "Installing every service runtime by hand makes an application hard to reproduce. This is the first state in the learning path that containerizes the TraderX application: its services and web frontend are packaged into container images instead of running as host-managed application processes. Docker Compose then defines how those containers run together, including configuration, networking, dependencies and NGINX ingress. For developers coming from the uncontainerized stack, the lesson is both how the application is packaged and how its containers are coordinated.",
  "entryAssumptions": "The harness and proxied application depend on host-installed service runtimes.",
  "concepts": [
    "Containerization packages an application component and its runtime dependencies into an image. A Dockerfile describes how that image is built; a container is a running instance of an image.",
    "Docker Compose describes how multiple containers run together: which images to build or use, their environment settings, networks, ports and dependencies. Packaging an application into images and coordinating its containers are distinct responsibilities.",
    "Compose networking uses service names; localhost inside a container refers to that container. The Docker engine still runs on a host, and source generation or image builds can still require host tooling."
  ],
  "runtimePrerequisites": "Use the state quickstart for tool versions, generation, start and stop commands. Run one local state at a time because ports and generated output directories are shared.",
  "entryMode": "combined",
  "transitions": [
    {
      "from": "003-agentic-harness-foundation",
      "carriesForward": "Add generated instructions, architecture context and contributor guidance for repeatable agent-assisted work.",
      "motivation": "The harness and proxied application depend on host-installed service runtimes.",
      "increment": "Containerize the application services and web frontend, then use Docker Compose to run the containers together behind NGINX and check readiness.",
      "objectiveIds": [
        "containerize-application",
        "trace-increment",
        "interpret-evidence"
      ],
      "evidence": "Identify a backend Dockerfile and the frontend Dockerfile, their built images and running containers, then show how Compose supplies the runtime wiring. The business workflow is retained while process placement changes. Container state, service readiness and successful booking are three different observations. A running container can still be unavailable during initialization. Recovery of a read route does not prove that an uncertain write failed."
    }
  ],
  "before": "The harness and proxied application depend on host-installed service runtimes.",
  "after": "Containerize the application services and web frontend, then use Docker Compose to run the containers together behind NGINX and check readiness.",
  "objectives": [
    {
      "id": "containerize-application",
      "outcome": "Trace a backend service and the web frontend from their Dockerfiles to built images and running containers, and distinguish image packaging from Compose runtime configuration."
    },
    {
      "id": "trace-increment",
      "outcome": "Map the retained trade workflow to Compose services and distinguish container state, readiness and a successful business result."
    },
    {
      "id": "interpret-evidence",
      "outcome": "Explain the evidence boundary: A running container can still be unavailable during initialization. Recovery of a read route does not prove that an uncertain write failed."
    }
  ],
  "walkthrough": [
    {
      "id": "inspect-containerization",
      "objectiveIds": [
        "containerize-application"
      ],
      "availability": "available",
      "action": "Generate state 004 using the quickstart. Under generated/code/target-generated, inspect account-service/Dockerfile.compose and web-front-end/angular/Dockerfile.compose. Identify the base image, the application artifacts copied or built into it, and the command that starts the component. Then follow the quickstart start command to build and run the stack. Use docker image ls and docker ps to identify the resulting images and containers, and compare their names and configuration with the generated Compose definition.",
      "expected": "Application components that previously ran as host-managed processes now run from container images. The frontend image serves the production/static application. The Dockerfiles define image contents and startup behavior; Compose connects and configures the containers. A successful image build alone does not establish service readiness or a working trade flow.",
      "references": [
        "/specs/containerized-compose-runtime/quickstart",
        "/specs/containerized-compose-runtime/system/runtime-topology"
      ]
    },
    {
      "id": "observe",
      "objectiveIds": [
        "trace-increment"
      ],
      "availability": "available",
      "action": "Generate and start the Compose state using the quickstart. Run its status and smoke commands. Compare the Compose service names, exposed ports and dependencies with the topology, then submit a small trade through ingress.",
      "expected": "The business workflow is retained while process placement changes. Container state, service readiness and successful booking are three different observations.",
      "references": [
        "/specs/containerized-compose-runtime/quickstart",
        "/specs/containerized-compose-runtime/system/architecture",
        "/specs/containerized-compose-runtime/system/runtime-topology"
      ]
    },
    {
      "id": "challenge",
      "objectiveIds": [
        "interpret-evidence"
      ],
      "availability": "available",
      "action": "In the disposable local stack, restart one application container identified in the generated Compose file. Watch status and retry a read through ingress after readiness returns; do not blindly resubmit a timed-out trade.",
      "expected": "A running container can still be unavailable during initialization. Recovery of a read route does not prove that an uncertain write failed.",
      "references": [
        "/specs/containerized-compose-runtime/spec"
      ]
    }
  ],
  "assessments": [
    {
      "objectiveIds": [
        "containerize-application"
      ],
      "question": "What does containerizing the application add beyond having a Compose file, and which parts of the runtime come from each?",
      "guidance": "Use the backend and frontend you inspected to identify their Dockerfiles, image contents and running containers. Explain how Compose selects or builds those images and supplies runtime configuration, networking and dependencies. Do not describe Compose configuration alone as the packaging of application code."
    },
    {
      "objectiveIds": [
        "trace-increment",
        "interpret-evidence"
      ],
      "question": "Why can Compose report running while the browser still receives an error?",
      "guidance": "Explain readiness and upstream dependencies using the restarted service. Show the later successful read and separately verify any uncertain trade."
    }
  ],
  "limitations": [
    "A running container can still be unavailable during initialization. Recovery of a read route does not prove that an uncertain write failed.",
    "This is an educational local demonstration. Passing its checks does not establish production readiness, financial settlement, or correctness under every failure mode."
  ],
  "coaching": [
    {
      "objectiveIds": [
        "containerize-application"
      ],
      "diagnosticQuestion": "How are the application services and frontend started in state 003, and where do their runtime dependencies live?",
      "predictionPrompt": "Before building state 004, predict which information belongs in an application Dockerfile and which belongs in the Compose definition.",
      "hints": [
        "Start with one backend and the frontend: identify the base image, application artifacts and startup command in each Dockerfile.",
        "Follow the images into the Compose services and identify the environment settings, networking and dependencies supplied when containers run."
      ],
      "misconception": "Adding a Compose file is the same as packaging the application, or all the application components were already containerized in the preceding learning state.",
      "evidenceToRequest": "Ask for the two inspected Dockerfiles, their images and running container identities, and an explanation separating application packaging from Compose runtime wiring."
    },
    {
      "objectiveIds": [
        "trace-increment",
        "interpret-evidence"
      ],
      "diagnosticQuestion": "What changes when localhost is evaluated inside a container rather than on your host?",
      "predictionPrompt": "Predict what the browser will observe while a restarted backend is running but not yet ready.",
      "hints": [
        "Separate container process status from the readiness of its dependencies.",
        "Trace the ingress request to that backend and compare its status before and after readiness returns."
      ],
      "misconception": "A running container establishes that the complete trading workflow is available.",
      "evidenceToRequest": "Ask for container/readiness observations, the ingress read result and independent evidence for any uncertain trade."
    }
  ]
}
