test(concurrent-interrupt): add missing _apply_pending_steer_to_tool_results no-op to _Stub#12574
Conversation
…results no-op to _Stub
``tests/run_agent/test_concurrent_interrupt.py`` binds the real
``AIAgent._execute_tool_calls_concurrent`` method (``run_agent.py:7940``+)
onto a minimal ``_Stub`` class, but the stub has drifted from the
production class: ``_execute_tool_calls_concurrent`` at
``run_agent.py:8092`` unconditionally calls
``self._apply_pending_steer_to_tool_results(messages, num_tools)`` at
the end of each tool batch, and the stub has no such method.
Result: both interrupt-path tests fail on clean ``origin/main``
(``6fb69229``)::
FAILED test_concurrent_interrupt_cancels_pending
FAILED test_running_concurrent_worker_sees_is_interrupted
AttributeError: '_Stub' object has no attribute
'_apply_pending_steer_to_tool_results'
Fix
---
Add a no-op ``_apply_pending_steer_to_tool_results`` to ``_Stub``,
matching the pattern of the existing no-op stub methods
(``_vprint``, ``_safe_print``, ``_should_emit_quiet_tool_messages``,
…).
These tests never exercise the ``/steer`` injection path — they
assert only interrupt propagation and worker cancellation. The real
method would early-return anyway (``_drain_pending_steer`` returns
``None`` when ``_pending_steer`` is unset), so a no-op is
behaviourally equivalent for this test surface without requiring the
stub to also carry ``_drain_pending_steer`` / ``_pending_steer`` /
``_pending_steer_lock`` state.
Validation
----------
``source venv/bin/activate && python -m pytest
tests/run_agent/test_concurrent_interrupt.py -q`` → **4 passed** on
the branch (was ``2 failed, 2 passed`` on ``origin/main``).
Broader ``tests/run_agent/`` under ``-n auto`` → **783 passed, 7
skipped, 0 failures** — no regression in any other tests that exercise
the stub pattern or the production ``_execute_tool_calls_concurrent``
path.
Scope
-----
Test-only change. Zero production-code impact. Narrow to the two
failing tests — no other baseline failures are touched by this PR.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes test-only drift in the concurrent-interrupt test stub so it matches the current internal AIAgent API shape and no longer fails with AttributeError on clean main.
Changes:
- Add missing no-op
_apply_pending_steer_to_tool_results(...)method to the_Stubused bytests/run_agent/test_concurrent_interrupt.py.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
CI notes on the initial run:
Focused suite on branch: Happy to rebase if a rerun would help — I don't have admin rights on the repo, so I can't trigger one directly. |
…match __init__
``tests/run_agent/test_interrupt_propagation.py::_make_bare_agent``
constructs an ``AIAgent`` via ``__new__``, bypassing ``__init__``, and
manually wires up the interrupt-related attributes used by the tests.
``AIAgent.__init__`` (``run_agent.py:736``) sets ``self.provider`` but
``_make_bare_agent`` did not.
Under the full ``tests/`` suite with pytest-xdist (``-n auto``), the
``test_interrupt_during_child_api_call_detected`` path can reach
``_create_openai_client`` (``run_agent.py:4660``, ``4671``) which
accesses ``self.provider`` directly (not via ``getattr``), raising::
AttributeError: 'AIAgent' object has no attribute 'provider'
The mocked-client fast-path in ``_create_request_openai_client``
normally short-circuits before reaching that code, but under xdist
worker-import ordering the short-circuit doesn't always engage, so the
test fails intermittently in CI while passing in isolation and under
broader-but-not-full module invocations.
Fix
---
Seed ``agent.provider = ""`` in the ``_make_bare_agent`` helper so the
bare agent matches what ``__init__`` would produce for the same
attribute. Same surgical pattern as the landed
``1cf10b45`` (NousResearch#12574) ``_Stub`` fix in
``tests/run_agent/test_concurrent_interrupt.py`` — test-only, zero
production-code change, minimal scope.
Validation
----------
``source venv/bin/activate && python -m pytest
tests/run_agent/test_interrupt_propagation.py -q`` → **7 passed**.
Broader ``tests/run_agent/`` under ``-n auto`` → **781 passed, 7
skipped, 0 new failures** (the 2 existing
``test_concurrent_interrupt`` failures are the separately-tracked
baseline handled by NousResearch#12574).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Closing as superseded — the exact stub fix landed upstream in stub._apply_pending_steer_to_tool_results = lambda *a, **kw: NoneExactly matching this PR. Good outcome — the cleanup sweep caught it. Closing to keep the queue tidy. |
TL;DR
tests/run_agent/test_concurrent_interrupt.py::_Stubis missing_apply_pending_steer_to_tool_results, so both concurrent-interrupt tests fail on cleanorigin/mainwithAttributeError. This is test-only drift — production code is unaffected.Fixing this takes two tests off the repo's standing baseline-failure list that's currently blocking every open PR's
testcheck.Root cause
_execute_tool_calls_concurrent(run_agent.py:7940+) is bound onto a minimal_Stubclass for these tests. Atrun_agent.py:8092the method unconditionally calls:That method was added to
AIAgentatrun_agent.py:3339but the stub was never updated. Every invocation of the interrupt-path tests raises:Reproduces on clean
origin/main(6fb69229):$ python -m pytest tests/run_agent/test_concurrent_interrupt.py -q 2 failed, 2 passed in 3.16s FAILED test_concurrent_interrupt_cancels_pending FAILED test_running_concurrent_worker_sees_is_interruptedFix
Add a no-op
_apply_pending_steer_to_tool_resultsto_Stub, matching the existing pattern for the other stub methods (_vprint,_safe_print,_should_emit_quiet_tool_messages,_has_stream_consumers, …).Why a no-op (rather than mirroring the real method's state machine):
_pending_steeror exercise the/steerinjection path._drain_pending_steerreturnsNonewhen_pending_steeris unset), so a no-op is behaviourally equivalent for this test surface._drain_pending_steer+_pending_steer+_pending_steer_lockstate that isn't under test.Validation
Broader
tests/run_agent/under-n auto→ 783 passed, 7 skipped, 0 failures.Narrow scope — explicitly not changed
run_agent.pyis unmodified.Pre-empted review questions
Q. Should the stub track
_pending_steerstate instead, to better mirror production?The existing stub is deliberately minimal (see its other
_vprint/_safe_print/… no-ops). The tests don't exercise the steer path, so carrying that state would be speculative complexity. If a future test does want to exercise/steerinjection during concurrent interrupt, that test can extend the stub then — per its actual needs.Q. Why not fix it in production (make
_execute_tool_calls_concurrenttolerant of a missing method)?Because nothing is wrong in production —
AIAgentalways has this method. The bug is purely in the test stub that drifted from the class it's shadowing.Co-authored via LLM assistance; I've reviewed every line and am responsible for correctness.