Skip to content

feat: Add E2E tests for the coding-agent adapters (claude_sdk, codex) - #635

Open
AlexanderZ-Band wants to merge 2 commits into
mainfrom
feat/add-e2e-tests-for-the-coding-agents-python-sdk-INT-1448
Open

AlexanderZ-Band wants to merge 2 commits into
mainfrom
feat/add-e2e-tests-for-the-coding-agents-python-sdk-INT-1448

Conversation

@AlexanderZ-Band

@AlexanderZ-Band AlexanderZ-Band commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • test_codex.py: regression-guard smoke restored (deleted in fc62742c).
  • test_claude_sdk.py: new smoke proving Band's chat-based approval relay gates a real Claude Code native tool call end-to-end.
  • _build_claude_sdk: per-cell disposable cwd (matrix cells previously ran Claude Code against this repo's own checkout).
  • claude_sdk.py: approval prompt/resolution strings extracted into named constants (APPROVAL_REQUESTED_TEMPLATE, APPROVAL_RESOLVED_TEMPLATE), mirroring opencode/approvals.py.
  • _pre_tool_use_continue_hook: returns hookSpecificOutput.permissionDecision="ask" instead of {"continue_": True}, which carried no permission decision — native tool calls (Bash/Write/Edit) were never reaching can_use_tool under the adapter's default permission_mode.
  • on_message: a turn now runs as a detached task and only awaits its early release (mirrors OpencodeAdapter's release_turn_wait/turn_future split). Band's runtime processes one room-message cycle at a time; a manual approval must release that cycle so the room can dispatch the reply that resolves it.

Test plan

  • ruff check . / ruff format --check . / pyrefly check
  • uv run pytest tests/ --ignore=tests/integration/ --ignore=tests/e2e/ -v — 5592 passed
  • E2E_TESTS_ENABLED=true BAND_E2E_LANE=core uv run pytest tests/e2e/baseline/smoke/adapters/test_claude_sdk.py -v -s --no-cov
  • E2E_TESTS_ENABLED=true BAND_E2E_LANE=backends uv run pytest tests/e2e/baseline/smoke/adapters/test_codex.py -v -s --no-cov
  • tests/e2e/baseline/guards/test_adapter_registry.py — 8 passed

Closes INT-1448.

🤖 Generated with Claude Code

https://claude.ai/code/session_01PycgygL3XZiSheL4CpquPM

Restores test_codex.py's regression-guard smoke (deleted in fc62742) and
adds a new claude_sdk manual-approval smoke, both proving the coding-agent
adapters' live-only behavior end-to-end. Fixes two real bugs the new
claude_sdk smoke uncovered:

- _pre_tool_use_continue_hook returned {"continue_": True}, which carries no
  permission decision, so native tool calls (Bash/Write/Edit) never actually
  reached can_use_tool under the adapter's default permission_mode -- manual
  approval silently never gated them. Fixed to return
  hookSpecificOutput.permissionDecision="ask", the SDK's real delegation
  mechanism.
- Even with that fixed, approval_mode="manual" deadlocked: Band's runtime
  processes one room-message cycle at a time, but on_message blocked
  synchronously inside that cycle waiting on a chat reply only a later
  cycle could deliver. on_message now runs a turn as a detached task and
  only awaits its early release (mirroring OpencodeAdapter's
  release_turn_wait/turn_future split), so a manual approval can free the
  room to dispatch the reply that resolves it.

Also fixes _build_claude_sdk's cwd hermeticity (no explicit cwd meant every
matrix cell ran Claude Code against this repo's own checkout) and extracts
the adapter's approval prompt/resolution strings into named constants so the
new smoke anchors on them instead of duplicating the wording.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PycgygL3XZiSheL4CpquPM
@linear-code

linear-code Bot commented Sep 14, 2026

Copy link
Copy Markdown

INT-1448

@AlexanderZ-Band
AlexanderZ-Band requested a review from a team September 14, 2026 15:10

@AlexanderZ-Band AlexanderZ-Band left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two lifecycle defects found: E2E workspaces leak, and an old detached turn can release a replacement turn after cleanup/rejoin.

Comment thread tests/e2e/baseline/toolkit/builders.py Outdated
Comment thread src/band/adapters/claude_sdk.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant