test(interrupt-propagation): seed provider attr on bare agent to match __init__#12908
test(interrupt-propagation): seed provider attr on bare agent to match __init__#12908briandevans wants to merge 2 commits into
Conversation
…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>
There was a problem hiding this comment.
Pull request overview
Test-only change to eliminate an intermittent pytest-xdist failure where a bare AIAgent stub (constructed via __new__) can reach code that reads self.provider directly and crash with AttributeError.
Changes:
- Seed
agent.provider = ""in the bare-agent factory used by interrupt propagation tests. - Add an explanatory comment documenting why the attribute is required when bypassing
__init__.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… (follow-up to NousResearch#12908) Previous commit seeded only ``provider``. The next CI run (Tests [24655838688](https://github.com/NousResearch/hermes-agent/actions/runs/24655838688)) shows the same test now trips on ``self.model``: FAILED test_interrupt_during_child_api_call_detected - AttributeError: 'AIAgent' object has no attribute 'model' Hit pattern NousResearch#8 from my own pre-push self-review checklist: "fixed one call site, missed sibling with same pattern." The ``_create_openai_client`` path reads ``self.provider``, ``self.model``, and ``self.base_url`` directly — if the mocked-client short-circuit doesn't engage (as apparently happens under xdist here), each missing attr surfaces as its own ``AttributeError``. Seed all three core identity attrs that ``AIAgent.__init__`` sets (run_agent.py:708, 734, 736) to make the bare-agent stub robust against any code path that touches them. Zero production-code change. 7 focused tests still pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Self-correction: my initial commit only seeded Hit pattern #8 from my pre-push self-review checklist ("fixed one call site, missed sibling with same pattern"). Pushed Baseline-failure classification for the Tests job is unchanged (same 4 pre-existing xdist flakes; |
|
CI on ✅ Remaining failures on this run (3, down from 4 on the initial push) are all standing baselines that pre-exist this PR and reproduce on clean
None touch |
|
Supply-chain Quick version: Was masked pre- |
|
Closing as superseded — all three attrs this PR seeded ( agent.provider = "openrouter"
agent.model = "test/model"
agent._base_url = "http://localhost:1234"Exactly the trio this PR proposed. Clean landing via the broader test-robustness sweep — closing to keep the queue tidy. |
TL;DR
Same class of bug as my landed #12574 — a test stub that uses
AIAgent.__new__(AIAgent)skips__init__and therefore missesself.provider. The fulltests/suite under pytest-xdist intermittently hits a code path that readsself.providerdirectly (withoutgetattr), causingAttributeError: 'AIAgent' object has no attribute 'provider'.Test-only change. Zero production-code touched.
Symptom
From the Tests run on #12889 (24655153236):
Appears on every recent PR's Tests job under
-n auto; passes in isolation and under most narrower invocations.Root cause
AIAgent.__init__setsself.provideratrun_agent.py:736. The bare-agent helper in this test file bypasses__init__:test_interrupt_during_child_api_call_detectedsetschild.client = MagicMock()expecting the Mock fast-path in_create_request_openai_clientto short-circuit:Under pytest-xdist worker-import ordering, the short-circuit doesn't always engage, and the code reaches
_create_openai_clientatrun_agent.py:4660/4671:→
AttributeError.Fix
Seed
agent.provider = ""in_make_bare_agent, matching what__init__would produce:Narrow scope — explicitly not changed
self.provideraccesses in_create_openai_clientare correct for the real call path (real agents always haveproviderset by__init__); the test harness just needs to mirror that invariant._make_bare_agent's intent — it's still a bare stub wiring only what interrupt tests need.Validation
Broader
tests/run_agent/under-n auto→ 781 passed, 7 skipped, 0 new failures. The 2test_concurrent_interruptfailures that remain are the separately-tracked baseline handled by #12574 (landed as1cf10b45).Related
Same surgical pattern as #12574 (landed —
_Stubintest_concurrent_interrupt.pymissing_apply_pending_steer_to_tool_results). Each time a prod refactor adds a new attribute or method read unconditionally along a path the test stub reaches, the bare-stub test harness drifts and needs a one-line seed. Each fix is test-only and reduces the baseline-flake set that blocks every contributor's CI.Co-authored via LLM assistance; I've reviewed every line and am responsible for correctness.