feat(auto-agents): retire implementation-worker wrapper (R2 wrapper-chain tax)

The depth-0 implementation-worker agent was a pure passthrough whose
only LLM-side responsibility was translating the dispatcher-built
prompt into tier-dispatcher's input format (top-level params +
``task_prompt:`` fenced body). Deterministic Python now does the
same translation in microseconds, removing one full LLM hop (and
its summarization-risk warning prose) from every implementer cycle.

What changed:

1. **New ``_wrap_for_tier_dispatcher`` helper** in
   ``tools/dispatch_implementer.py`` — emits the exact format
   documented in ``.opencode/agents/tier-dispatcher.md``: outer-level
   ``task_agent: \`task-implementor\``` + ``estimator_agent:
   \`estimator-implementation\``` + optional ``escalation_tier_hint``
   line, then the body verbatim inside a fenced ``task_prompt:``
   block.

2. **``_implementation_prompt_dispatch`` refactored** to compute
   the escalation_tier_hint upfront (start_tier vs estimator-flag
   logic preserved exactly) and wrap+return once. The three prior
   return paths (early-return / explicit-hint / final-extras) all
   funnel through the same wrap helper.

3. **WORK_GROUP defs swapped**: three ``worker_agent="implementation-
   worker"`` → ``"tier-dispatcher"`` so the dispatcher invokes
   tier-dispatcher directly as the top-level OpenCode session.

4. **``release_claim_on_exit`` removed** from the emitted prompt.
   It was an implementation-worker-only directive telling the
   wrapper to skip its own session-end release; tier-dispatcher
   has never read it. The dispatcher's ``finally`` block has
   always owned the actual claim lifecycle and is unchanged.

5. **Test updates**: three test files updated to match the new
   contract — assert absence of ``release_claim_on_exit`` and
   ``worker_agent == "tier-dispatcher"``. All other tests pass
   without modification (the wrapper's .md file remains as
   historical doc; can be deleted in a follow-up cleanup).

Audit confirmed no permission boundary lost (both agents are
``mode: all`` with equivalent bash/write allowlists), no agent-
name conditionals in ``_opencode_worker``, no archive-filename
grep filtering, tier-dispatcher input format is a 1:1 superset
of what the wrapper emits.

Live-cycle savings: removes the wrapper's ~1.5–3K tokens of
reasoning + tool overhead, removes one full session-creation +
session-archive cycle, removes the "verbatim forwarding"
summarization risk (deterministic Python can't lose sections).
Chain shrinks from 4 levels (impl-worker → tier-dispatcher →
estimator/tier-N → task-implementor) to 3 (tier-dispatcher →
estimator/tier-N → task-implementor).

Full auto_agents suite: 2056 passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-16 16:10:01 -04:00
parent ea4a96aad6
commit 6e63073ad9
4 changed files with 96 additions and 42 deletions
+16 -6
View File
@@ -1425,9 +1425,17 @@ class TestEstimatorEnabledFlag:
prompt = driver._implementation_prompt_dispatch(cfg, item, group)
assert self._hint_line(prompt) == "escalation_tier_hint: `0`"
assert "release_claim_on_exit: false" in prompt, (
"escalation-enabled prompt must still tell the worker to "
"skip its session-end claim release"
# R2 (2026-05-16): with the implementation-worker wrapper
# retired, the dispatcher emits the tier-dispatcher input
# format directly. ``release_claim_on_exit`` was a wrapper-
# only directive (telling the wrapper to skip its own
# session-end claim release) — it has no role in
# tier-dispatcher's contract, so the dispatcher OMITS it.
# The actual claim release stays in the dispatcher's
# ``finally`` block, unchanged.
assert "release_claim_on_exit" not in prompt, (
"release_claim_on_exit is a retired wrapper directive; "
"tier-dispatcher's input format does not include it"
)
def test_escalation_on_estimator_on_first_attempt_omits_hint(
@@ -1435,8 +1443,7 @@ class TestEstimatorEnabledFlag:
):
"""Estimator ON + escalation ON + no resumption label = true
first attempt: the dispatcher OMITS the hint so the estimator
runs. ``release_claim_on_exit: false`` is still emitted (the
dispatcher holds the claim across tier attempts)."""
runs."""
monkeypatch.setenv("IMPLEMENTER_ESCALATION_ENABLED", "1")
monkeypatch.setenv("IMPLEMENTER_ESTIMATOR_ENABLED", "1")
monkeypatch.setenv("IMPLEMENTER_DISPATCHER_PREFETCH", "0")
@@ -1456,7 +1463,10 @@ class TestEstimatorEnabledFlag:
"true-first-attempt with estimator ON must omit the hint; "
f"got {self._hint_line(prompt)!r}"
)
assert "release_claim_on_exit: false" in prompt
# R2: ``release_claim_on_exit`` no longer emitted
# (implementation-worker wrapper retired; see comment in
# ``test_escalation_on_estimator_off_first_attempt_emits_hint_zero``).
assert "release_claim_on_exit" not in prompt
def test_resumption_label_emits_hint_regardless_of_estimator_flag(
self, driver, cfg, monkeypatch
+4 -1
View File
@@ -973,7 +973,10 @@ def test_implementer_issue_group_does_not_claim(runtime):
assert issue_group.item_kind == "issue"
assert issue_group.claim_kind is None
assert issue_group.worker_agent == "implementation-worker"
# R2 (2026-05-16): the implementation-worker wrapper is retired
# and the dispatcher invokes tier-dispatcher directly. Saves one
# full LLM hop per cycle.
assert issue_group.worker_agent == "tier-dispatcher"
def _make_loop_cfg(runtime, tmp_path, *, budget):
@@ -2372,7 +2372,13 @@ class TestClaimReleaseDirective:
prompt = driver._implementation_prompt_dispatch(cfg, item, group)
assert "release_claim_on_exit: false" in prompt
# R2 (2026-05-16): the implementation-worker wrapper was
# retired; its ``release_claim_on_exit`` directive is no
# longer emitted (tier-dispatcher has never read that flag,
# and the dispatcher's own ``finally`` block has always owned
# the actual claim release). Asserting absence keeps the
# contract pinned now that the directive is dead.
assert "release_claim_on_exit" not in prompt
def test_flag_off_pr_prompt_does_not_carry_directive(
self, driver, cfg, monkeypatch
+69 -34
View File
@@ -1657,6 +1657,45 @@ def _maybe_short_circuit(
}
def _wrap_for_tier_dispatcher(
body: str, *, escalation_tier_hint: int | None = None,
) -> str:
"""Wrap a dispatcher-built body for ``tier-dispatcher``'s
expected input format.
Replaces the ``implementation-worker`` wrapper which previously
did this translation as a 1.53K-token LLM hop (depth-0 of the
chain). Deterministic Python produces byte-identical output for
every PR and removes one full agent round-trip from each cycle.
Format documented in ``.opencode/agents/tier-dispatcher.md``
outer-level ``task_agent`` / ``estimator_agent`` parameter
lines, optional ``escalation_tier_hint``, and the body wrapped
in a fenced ``task_prompt:`` block. The body MAY itself contain
credential lines and ``## Pre-fetched …`` sections; both are
forwarded verbatim. tier-dispatcher reads the outer parameters
and then embeds ``task_prompt`` into the estimator + tier-N
calls verbatim per its documented contract.
Note ``release_claim_on_exit`` is intentionally OMITTED: that
was an implementation-worker directive telling the wrapper to
skip its own claim-release at session end. The dispatcher's
own ``finally`` block has always owned the actual claim
lifecycle; the directive becomes dead prose once the wrapper
is gone.
"""
outer_lines = [
"task_agent: `task-implementor`",
"estimator_agent: `estimator-implementation`",
]
if escalation_tier_hint is not None:
outer_lines.append(
f"escalation_tier_hint: `{int(escalation_tier_hint)}`"
)
outer = "\n".join(outer_lines)
return f"{outer}\n\ntask_prompt:\n```\n{body}\n```\n"
def _implementation_prompt_dispatch(
cfg: Any, item: dict[str, Any], group: Any
) -> str:
@@ -1690,16 +1729,14 @@ def _implementation_prompt_dispatch(
# the worker should fall through to ``estimator-implementation``
# on the first attempt (G11 harvest 2026-05-15).
if not _is_escalation_enabled() or not is_pr_shape:
if estimator_enabled:
# OMIT the hint so ``tier-dispatcher`` runs the estimator
# and chooses an adaptive tier.
return base_prompt
# Default OFF: emit an explicit hint=0 so the worker passes
# it through and ``tier-dispatcher`` short-circuits to
# ``tier-0``. Byte-equivalent to today's flag-OFF prompt
# after the worker's no-hint→default-0 fallback is removed
# (see ``implementation-worker.md`` G11 edit).
return f"{base_prompt}\n\nescalation_tier_hint: `0`\n"
# Estimator ON → OMIT the hint so ``tier-dispatcher`` runs
# the estimator and chooses an adaptive tier. Estimator OFF
# → emit hint=0 so ``tier-dispatcher`` short-circuits to
# ``tier-0`` directly.
hint = None if estimator_enabled else 0
return _wrap_for_tier_dispatcher(
base_prompt, escalation_tier_hint=hint,
)
pr_number = int(item.get("number") or 0)
start_tier = _read_start_tier_from_labels(cfg, pr_number)
@@ -1716,28 +1753,26 @@ def _implementation_prompt_dispatch(
item["_dispatcher_implementer_context"] = context
context["start_tier"] = start_tier
# Tell the worker to skip its session-end claim release.
# When escalation is on, the dispatcher holds the claim across
# all tier attempts in this cycle and the dispatch_one finally
# block does the actual release. Without this directive, the
# worker's release between tiers leaves a 13 s window where
# another driver could grab the PR. See plan #5.
extras = ["release_claim_on_exit: false"]
# Resolve the escalation_tier_hint that tier-dispatcher consumes:
# - start_tier > 0 → label-driven cross-cycle resumption hint
# (the auto/last-attempt-tier-N label names the next tier
# explicitly; the estimator cannot override).
# - start_tier == 0 AND estimator OFF → emit hint=0 so
# tier-dispatcher short-circuits to tier-0 (legacy default).
# - start_tier == 0 AND estimator ON → OMIT the hint so
# tier-dispatcher falls through to estimator-implementation.
#
# ``release_claim_on_exit`` is no longer emitted (R2, 2026-05-16
# implementation-worker retirement): the dispatcher's outer
# ``finally`` block has always owned the actual claim lifecycle;
# the directive was a wrapper-only flag telling the (now-retired)
# wrapper to skip its own session-end release.
if start_tier > 0:
# Cross-cycle resumption: ``auto/last-attempt-tier-N`` labels
# name the next tier explicitly. The estimator cannot override
# label-driven resumption — even when ``estimator_enabled`` is
# True the hint is emitted so the worker resumes at the
# correct tier.
extras.append(f"escalation_tier_hint: `{start_tier}`")
hint: int | None = start_tier
elif not estimator_enabled:
# Estimator OFF on a true first attempt (no resumption labels):
# emit the explicit hint=0 fallback so the worker short-circuits
# to ``tier-0`` — byte-for-byte the legacy behaviour.
extras.append("escalation_tier_hint: `0`")
# else: estimator ON, first attempt — OMIT the hint so the worker
# falls through to ``estimator-implementation``.
final_prompt = f"{base_prompt}\n\n" + "\n".join(extras) + "\n"
hint = 0
else:
hint = None
# P0 / A: deterministic short-circuit.
# If the prefetch + deterministic sections + remote CI state all
@@ -1749,7 +1784,7 @@ def _implementation_prompt_dispatch(
# for the auto-fix path; the no-op skip case fires whenever
# escalation is on and conditions are met).
_maybe_short_circuit(cfg, item, context)
return final_prompt
return _wrap_for_tier_dispatcher(base_prompt, escalation_tier_hint=hint)
# ─── Post-session action: cleanup pre-cloned worktree ───────────────────────
@@ -3065,7 +3100,7 @@ WORK_GROUPS = [
script_name="list_prs_ci_failing",
item_kind="pr",
claim_kind=CLAIM_KIND,
worker_agent="implementation-worker",
worker_agent="tier-dispatcher",
tag_prefix="AUTO-IMP",
prompt_factory=_implementation_prompt_dispatch,
post_session_action=_dispatch_post_session_action,
@@ -3075,7 +3110,7 @@ WORK_GROUPS = [
script_name="list_prs_changes_requested",
item_kind="pr",
claim_kind=CLAIM_KIND,
worker_agent="implementation-worker",
worker_agent="tier-dispatcher",
tag_prefix="AUTO-IMP",
prompt_factory=_implementation_prompt_dispatch,
post_session_action=_dispatch_post_session_action,
@@ -3085,7 +3120,7 @@ WORK_GROUPS = [
script_name="list_issues",
item_kind="issue",
claim_kind=None,
worker_agent="implementation-worker",
worker_agent="tier-dispatcher",
tag_prefix="AUTO-IMP",
prompt_factory=_implementation_prompt_dispatch,
post_session_action=_dispatch_post_session_action,