fix(test_concurrent_interrupt): add _tool_guardrails to _Stub fixture (partial close hermes-agent#9) #13

Merged
claude-ceo-assistant merged 1 commits from fix/concurrent-interrupt-stub-guardrails into main 2026-05-08 21:03:44 +00:00

1 Commits

Author SHA1 Message Date
dev-lead
b200cba562 fix(test_concurrent_interrupt): add _tool_guardrails to _Stub fixture (partial close hermes-agent#9)
Some checks failed
Nix / nix (macos-latest) (pull_request) Waiting to run
Supply Chain Audit / Scan PR for critical supply chain risks (pull_request) Successful in 19s
Contributor Attribution Check / check-attribution (pull_request) Failing after 19s
Tests / e2e (pull_request) Successful in 32s
Tests / test (pull_request) Failing after 8m0s
Nix / nix (ubuntu-latest) (pull_request) Failing after 12m25s
The `_Stub` fixture in tests/run_agent/test_concurrent_interrupt.py
bypasses `AIAgent.__init__`, so it must mirror any new instance attributes
that production methods rely on. Tool-loop guardrails (introduced in
58b89965 "fix(agent): add tool-call loop guardrails", 2026-04-27) added
three integration points to `_execute_tool_calls_concurrent`:

1. `self._tool_guardrails.before_call(...)` per tool (run_agent.py:9447)
2. `self._append_guardrail_observation(...)` per result (run_agent.py:9672)
3. `self._guardrail_block_result(...)` for blocked calls

`_Stub` defined none of these, so both
`test_concurrent_interrupt_cancels_pending` and
`test_running_concurrent_worker_sees_is_interrupted` raised
`AttributeError: '_Stub' object has no attribute '_tool_guardrails'`
on the first concurrent tool call.

Fix:
- Add a real `ToolCallGuardrailController()` instance attribute, matching
  AIAgent.__init__ at run_agent.py:1160. Default config is warning-only
  so the controller observes but never blocks — the tests still exercise
  interrupt fanout, not guardrail behaviour.
- Bind the real `_append_guardrail_observation` and `_guardrail_block_result`
  helpers from AIAgent (same pattern as the existing `_execute_tool_calls_concurrent`
  / `interrupt` / `clear_interrupt` bindings).
- Stub `_set_tool_guardrail_halt` as a no-op + add `_tool_guardrail_halt_decision = None`.
- Widen `slow_tool` and `polling_tool` side-effect signatures with `**kwargs`
  to swallow new production-only `_invoke_tool` kwargs (`messages`,
  `pre_tool_block_checked`).

Verification:
- pytest tests/run_agent/test_concurrent_interrupt.py -v   # 4/4 pass
- pytest tests/run_agent/                                  # 1193 passed,
  9 skipped, only pre-existing test_primary_runtime_restore failure
  (issue #9 cluster, untouched here).

Diff scope: single file, 21 insertions, 2 modifications.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:02:21 -07:00