From 9b80207ab4ad36797cfc4dc70d88d269063bab4d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 01:47:21 +0000 Subject: [PATCH 1/2] Initial plan From f58a4d450393dccf64f648c54e2b680067e4db18 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 01:49:15 +0000 Subject: [PATCH 2/2] Fix _is_service_healthy nil-pointer for containers without healthchecks Use a safe Go template that checks for Health before accessing Status, emitting "none" for containers without a healthcheck instead of relying on Go's "" output which caused a template error and exit code 1. Agent-Logs-Url: https://github.com/blondres04/shieldclaw/sessions/ab4886d3-942a-46a1-8b93-4ebee24687e9 Co-authored-by: blondres04 <91551702+blondres04@users.noreply.github.com> --- shield-claw/src/shieldclaw/sandbox/docker_orchestrator.py | 8 ++++---- shield-claw/tests/test_docker_orchestrator.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/shield-claw/src/shieldclaw/sandbox/docker_orchestrator.py b/shield-claw/src/shieldclaw/sandbox/docker_orchestrator.py index 110a231..fb11220 100644 --- a/shield-claw/src/shieldclaw/sandbox/docker_orchestrator.py +++ b/shield-claw/src/shieldclaw/sandbox/docker_orchestrator.py @@ -521,7 +521,7 @@ def _is_service_healthy(self, service_name: str, project: str, cwd: Path) -> boo Returns: ``True`` when the container is ``running`` and health is ``healthy`` - or ```` (no healthcheck configured). ``False`` otherwise. + or ``none`` (no healthcheck configured). ``False`` otherwise. """ for sep in ("-", "_"): container = f"{project}{sep}{service_name}{sep}1" @@ -529,7 +529,7 @@ def _is_service_healthy(self, service_name: str, project: str, cwd: Path) -> boo "docker", "inspect", "--format", - "{{.State.Health.Status}}\t{{.State.Status}}", + "{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}\t{{.State.Status}}", container, ] _LOG.debug("Running command: %s", cmd) @@ -551,8 +551,8 @@ def _is_service_healthy(self, service_name: str, project: str, cwd: Path) -> boo health, _, status = output.partition("\t") if status.strip() != "running": return False - # "" means no healthcheck is configured — treat as passing. - return health.strip() in ("healthy", "", "") + # "none" means no healthcheck is configured — treat as passing. + return health.strip() in ("healthy", "none", "") return False def _wait_for_compose_ready( diff --git a/shield-claw/tests/test_docker_orchestrator.py b/shield-claw/tests/test_docker_orchestrator.py index 46ff86d..2ed0611 100644 --- a/shield-claw/tests/test_docker_orchestrator.py +++ b/shield-claw/tests/test_docker_orchestrator.py @@ -173,8 +173,8 @@ def test_is_service_healthy_healthy_with_healthcheck(mocker: MockerFixture) -> N def test_is_service_healthy_no_healthcheck_counts_as_passing(mocker: MockerFixture) -> None: - """```` health status (no healthcheck) must return ``True`` when running.""" - proc = subprocess.CompletedProcess(["docker", "inspect"], 0, "\trunning", "") + """``none`` health status (no healthcheck) must return ``True`` when running.""" + proc = subprocess.CompletedProcess(["docker", "inspect"], 0, "none\trunning", "") mocker.patch("shieldclaw.sandbox.docker_orchestrator.subprocess.run", return_value=proc) assert DockerOrchestrator()._is_service_healthy("web", "proj", Path("/tmp")) @@ -188,7 +188,7 @@ def test_is_service_healthy_unhealthy_returns_false(mocker: MockerFixture) -> No def test_is_service_healthy_not_running_returns_false(mocker: MockerFixture) -> None: """Container not yet in ``running`` state must return ``False``.""" - proc = subprocess.CompletedProcess(["docker", "inspect"], 0, "\texited", "") + proc = subprocess.CompletedProcess(["docker", "inspect"], 0, "none\texited", "") mocker.patch("shieldclaw.sandbox.docker_orchestrator.subprocess.run", return_value=proc) assert not DockerOrchestrator()._is_service_healthy("web", "proj", Path("/tmp")) @@ -205,7 +205,7 @@ def fake_inspect(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProce if len(calls) == 1: return subprocess.CompletedProcess(cmd, 1, "", "No such container") # Second call (legacy underscore form) — success. - return subprocess.CompletedProcess(cmd, 0, "\trunning", "") + return subprocess.CompletedProcess(cmd, 0, "none\trunning", "") mocker.patch("shieldclaw.sandbox.docker_orchestrator.subprocess.run", side_effect=fake_inspect) assert DockerOrchestrator()._is_service_healthy("web", "myproject", Path("/tmp"))