fix(grok): unbreak workspace-cwd agents, free trapped agents, stop self-PR review

Three bugs surfaced by the first live Grok lifecycle run:

- Dev/QA/doc agents crash-looped at startup with ModuleNotFoundError on
  roboco.llm.providers. The entrypoint ran the opencode-config render from the
  agent's workspace-clone cwd, whose own roboco/ dir shadows /app on the
  sys.path front; a branch without the grok code lacks the providers package.
  Render from /app so the installed package always resolves (the render has no
  cwd dependency — writes global, reads ROBOCO_MCP_CONFIG).

- A budget/loop halt blocked EVERY tool, including i_am_idle, unclaim, and
  i_am_blocked, so a halted agent could neither continue nor stop and flailed —
  one billed model turn per blocked retry. The before-gate now always lets the
  release verbs through so a halted agent can exit cleanly.

- The inbound reviewer ingested the org's OWN PRs (authored by the repo-owner
  account), which can't take a REQUEST_CHANGES review (GitHub 422) and get
  re-reviewed every poll. The normalizer flags author_is_owner and ingestion
  skips them — the reviewer reviews only PRs the org did not author.
  External/contributor PRs are unaffected.

Tests: owner-authored PR flagged + skipped; normalize shape covers the new
field. Gate green on the changed modules (ruff/mypy/xenon + 48 tests).
This commit is contained in:
Renn F
2026-06-19 00:44:42 +02:00
parent 059dc91a4f
commit d1d1b638ae
6 changed files with 71 additions and 2 deletions
@@ -196,3 +196,24 @@ async def test_skip_internal_when_disabled(monkeypatch: pytest.MonkeyPatch) -> N
)
assert ok is False
svc.ingest_external_pr.assert_not_awaited()
@pytest.mark.asyncio
async def test_skip_owner_authored_pr(monkeypatch: pytest.MonkeyPatch) -> None:
# The org's own account opened the PR → self-review, never ingest (even with
# both review modes on). The reviewer reviews PRs the org did NOT author.
monkeypatch.setattr(orch_mod.settings, "external_pr_enabled", True)
monkeypatch.setattr(orch_mod.settings, "internal_pr_enabled", True)
svc = _svc()
pr = {
"number": 213,
"is_fork": False,
"author_is_owner": True,
"author_association": "OWNER",
"head_ref": "feat/grok-provider-seam",
}
ok = await _orch()._ingest_pr_if_reviewable(
svc, SimpleNamespace(id=uuid4()), pr, uuid4(), set()
)
assert ok is False
svc.ingest_external_pr.assert_not_awaited()