feat(deploy): give the PR reviewer its own image, like every other agent

pr-reviewer-1 was the one agent with no dedicated image and no compose
builder service — it reused roboco-agent-base, which left it absent from the
compose files entirely (so it looked like the PR reviewer simply was not
there). Make it first-class for parity: add docker/agent-pr-reviewer.Dockerfile
(FROM the base — read-only reviewer, no extra toolchain), an
agent-pr-reviewer-image builder service in both compose files and the registry
compose, the image in the release workflow's publish list, and map
pr-reviewer-1 -> roboco-agent-pr-reviewer in the orchestrator plus its
lazy-build dockerfile map. Supersedes the earlier base-reuse mapping.
This commit is contained in:
Renn F
2026-06-17 00:56:56 +02:00
parent 00c467a894
commit 7a8c083c31
7 changed files with 57 additions and 8 deletions
+1
View File
@@ -99,6 +99,7 @@ jobs:
[roboco-agent-doc]=docker/agent-doc.Dockerfile
[roboco-agent-prompter]=docker/agent-prompter.Dockerfile
[roboco-agent-secretary]=docker/agent-secretary.Dockerfile
[roboco-agent-pr-reviewer]=docker/agent-pr-reviewer.Dockerfile
)
for name in "${!IMAGES[@]}"; do
echo "::group::build ${name}"
+5
View File
@@ -155,6 +155,11 @@ services:
entrypoint: ["/bin/sh", "-c", "echo 'agent-secretary image present'"]
restart: "no"
agent-pr-reviewer-image:
image: ${ROBOCO_REGISTRY:-ghcr.io/rennf93}/roboco-agent-pr-reviewer:${ROBOCO_VERSION:-latest}
entrypoint: ["/bin/sh", "-c", "echo 'agent-pr-reviewer image present'"]
restart: "no"
# --------------------------------------------------------------------------
# Orchestrator — API server + agent spawner
# --------------------------------------------------------------------------
+13
View File
@@ -216,6 +216,19 @@ services:
depends_on:
- agent-base-image
# ==========================================================================
# Agent PR Reviewer Image Builder (read-only reviewer of inbound external PRs)
# ==========================================================================
agent-pr-reviewer-image:
build:
context: .
dockerfile: docker/agent-pr-reviewer.Dockerfile
image: roboco-agent-pr-reviewer
entrypoint: ["/bin/sh", "-c", 'echo "Agent PR Reviewer image built"']
restart: "no"
depends_on:
- agent-base-image
# ==========================================================================
# Orchestrator - API Server + Agent Spawner
# ==========================================================================
+13
View File
@@ -216,6 +216,19 @@ services:
depends_on:
- agent-base-image
# ==========================================================================
# Agent PR Reviewer Image Builder (read-only reviewer of inbound external PRs)
# ==========================================================================
agent-pr-reviewer-image:
build:
context: .
dockerfile: docker/agent-pr-reviewer.Dockerfile
image: roboco-agent-pr-reviewer
entrypoint: ["/bin/sh", "-c", 'echo "Agent PR Reviewer image built"']
restart: "no"
depends_on:
- agent-base-image
# ==========================================================================
# Orchestrator - API Server + Agent Spawner
# ==========================================================================
+15
View File
@@ -0,0 +1,15 @@
# PR Reviewer Agent
#
# A read-only reviewer: fetches a PR diff via the GitHub API, greps the
# codebase, and posts one change-request. It never runs or builds the code (the
# trust boundary — execution only happens later in a dev cell during supersede),
# so it needs no language toolchain or test runner beyond the base image. It
# gets its own image for parity with every other agent and so the role is
# explicit on the compose + release surface. Keeps the base `claude` entrypoint
# — it is dispatched per review task like the dev/QA agents, not a persistent
# SDK driver like intake/secretary.
FROM roboco-agent-base
LABEL role="pr-reviewer"
LABEL description="Read-only PR reviewer - reviews inbound external PRs and posts one change-request"
+5 -5
View File
@@ -123,11 +123,10 @@ AGENT_IMAGES: dict[str, str] = {
"product-owner": "roboco-agent-pm",
"head-marketing": "roboco-agent-pm",
"auditor": "roboco-agent-pm",
# PR Reviewer — read-only reviewer (fetches the PR diff via API, greps the
# code, posts one change-request; never runs code). The base image has
# everything it needs, so it intentionally reuses it rather than shipping a
# dedicated image. Explicit (not a silent fallback) so the choice is visible.
"pr-reviewer-1": AGENT_BASE_IMAGE,
# PR Reviewer — read-only reviewer (diff via API, grep, post one
# change-request; never runs code). Its own image for parity with the other
# agents; built FROM the base, no extra toolchain.
"pr-reviewer-1": "roboco-agent-pr-reviewer",
# Intake — persistent Agent-SDK driver, not a one-shot `claude -p`.
INTAKE_AGENT_ID: "roboco-agent-prompter",
# Secretary — persistent Agent-SDK driver with gated CEO authority.
@@ -787,6 +786,7 @@ class AgentOrchestrator:
"roboco-agent-ux": "agent-ux.Dockerfile",
"roboco-agent-prompter": "agent-prompter.Dockerfile",
"roboco-agent-secretary": "agent-secretary.Dockerfile",
"roboco-agent-pr-reviewer": "agent-pr-reviewer.Dockerfile",
}
dockerfile = dockerfile_map.get(bare)
if dockerfile:
@@ -53,8 +53,10 @@ def test_get_agent_image_local_default(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(orch.settings, "agent_image_registry", "")
monkeypatch.setattr(orch.settings, "agent_image_tag", "")
assert orch.get_agent_image("be-dev-1") == "roboco-agent-dev-be"
# Unknown agent id falls back to the base image.
assert orch.get_agent_image("pr-reviewer-1") == "roboco-agent-base"
# The PR reviewer has its own image (parity with the other agents).
assert orch.get_agent_image("pr-reviewer-1") == "roboco-agent-pr-reviewer"
# A genuinely unknown agent id falls back to the base image.
assert orch.get_agent_image("nope-not-real") == "roboco-agent-base"
def test_get_agent_image_registry_mode(monkeypatch: pytest.MonkeyPatch) -> None:
@@ -66,5 +68,5 @@ def test_get_agent_image_registry_mode(monkeypatch: pytest.MonkeyPatch) -> None:
)
assert (
orch.get_agent_image("pr-reviewer-1")
== "ghcr.io/rennf93/roboco-agent-base:0.5.0"
== "ghcr.io/rennf93/roboco-agent-pr-reviewer:0.5.0"
)