* fix(e2e): resolve 12 E2E test failures across routines and features groups
Three root causes fixed:
1. Read-only thread regression (9 routines failures): ed2d6dc3 changed
loadThreads() to follow the server's active_thread on page load. When
a prior test creates an HTTP-channel thread, new browser pages auto-switch
to it — disabling the chat input. Fix: skip read-only channel threads
when auto-switching; also restore placeholder text in enableChatInput().
2. Tool approval state contamination (2 features failures):
test_chat_reply_always permanently auto-approves the http tool for the
session. Tests running after it that need the approval gate to fire
(test_text_approval_resolves_real_tool_call,
test_slash_approve_is_thread_scoped_api) find it pre-approved. Fix:
reorder so real-approval-gate tests run before the "always" test.
3. Silent /approve on idle thread (1 features failure):
/approve is always routed as an approval command. process_approval()
returns an empty message when no approval is pending, producing
HandleOutcome::NoResponse. send_chat_and_wait_for_terminal_message
times out waiting for a visible response. Fix: return "No pending
approval for this thread." so the response is visible.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(gateway): address henrypark133 review — readonly thread regression test (#2503)
- Remove redundant `!activeThread` guard in loadThreads() (threads.some()
already guarantees existence), use `const` instead of `var`
- Add E2E browser regression test: sets an external-channel (HTTP) thread
as the server active_thread, reloads without a hash, and asserts the UI
falls back to the assistant thread with chat input enabled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>