[F091] warn at spawn time when host grok auth.json is missing

GrokCliProvider._append_grok_auth_mount silently skipped the mount when
the host ~/.grok/auth.json was absent. The spawn still succeeded (docker
run returned 0 — the container was created), so the operator had no
spawn-time signal that the agent was doomed: the entrypoint's
`python -m roboco.llm.providers.grok_auth --check` backstop then
refused to start (exit 78) and the failure only surfaced later via the
container's log markers.

Fix: emit a spawn-time WARNING (module logger) naming the missing file
and the remediation (`grok login` on the host, or set
ROBOCO_HOST_GROK_DIR) when the mount is skipped. The spawn outcome is
unchanged — the container still starts and the existing exit-78 -> park
flow (F041) still catches it — but the operator now sees the missing
credential immediately instead of diagnosing a later exit-78.

Logical-regression check: the mount-present path is byte-for-byte
unchanged (auth.json exists -> the -v bind is appended, no warning); the
spawn still succeeds when auth is absent (no raise — the existing
test_grok_spawn_omits_auth_mount_when_absent still passes: no mount, no
crash); the exit-78 entrypoint backstop and the orchestrator's
exit-78-park handling (F041) are untouched; a module-level logger adds no
side effects. Tests: new test_grok_spawn_warns_when_auth_absent uses
caplog to assert a WARNING mentioning auth.json + `grok login` is
emitted on a missing-credential spawn (RED before: no warning; GREEN
after). 102 grok tests green; ruff/mypy clean.
This commit is contained in:
Renn F
2026-06-28 20:06:03 +02:00
parent 919aa7e24e
commit c44b32aea8
2 changed files with 36 additions and 0 deletions
+16
View File
@@ -27,6 +27,7 @@ from __future__ import annotations
import asyncio
import dataclasses
import logging
import os
from pathlib import Path
from typing import TYPE_CHECKING, Protocol
@@ -37,6 +38,8 @@ from roboco.llm.providers.base import AgentProvider, ProviderError, SpawnResult
if TYPE_CHECKING:
from roboco.models.runtime import OrchestratorAgentConfig as AgentConfig
_log = logging.getLogger(__name__)
# The Grok agent image (own image, like every other agent role). Overridable for
# tests / staged rollout.
_DEFAULT_GROK_IMAGE = os.environ.get(
@@ -179,6 +182,19 @@ class GrokCliProvider(AgentProvider):
auth_dir = Path(GROK_AUTH_HOST_PATH)
if (auth_dir / "auth.json").exists():
cmd.extend(["-v", f"{auth_dir}:{_GROK_AUTH_DIR_IN_CONTAINER}:ro"])
else:
# The mount is the grok subscription credential — without it the
# container starts but the entrypoint ``--check`` backstop refuses
# to run (exit 78) and the agent is doomed. Fail loud at spawn time
# so the operator sees the missing credential immediately instead
# of diagnosing a later exit-78 from the container log markers.
_log.warning(
"grok host auth.json not found at %s — spawn will start the "
"container but it is doomed to exit 78 (no SuperGrok credential). "
"Run `grok login` on the host (or set ROBOCO_HOST_GROK_DIR to the "
"directory holding auth.json) before spawning Grok agents.",
auth_dir / "auth.json",
)
@staticmethod
def _append_usage_mount(cmd: list[str], hosts: dict[str, str | None]) -> None: