fix(session): reconcile severed long turns against server state — no false 'failed to send' (#1376)#1377
Merged
Merged
Conversation
…ing (#1376) In Session mode the turn endpoint is synchronous; an intermediary (e.g. Cloudflare's ~100s edge timeout) can sever the socket while the backend keeps running and ultimately succeeds. The catch in sendMessage now reconciles against GET /sessions/{id} before declaring failure: a NEW assistant beyond the pre-send baseline is success (checked first, since the reply persists inside the inflight sentinel); turn_in_progress hands off to the reattach poller with no error; neither surfaces the real error. A 429 concurrent-turn reject short-circuits before the reconcile. A pre-persistence drop restores the optimistic user row. startPolling now bounds on a wall-clock deadline (~2h, covering the sentinel TTL) instead of an attempt count that background-tab throttling made unreliable, and routes the deadline outcome through a neutral noticeBySession channel instead of errorBySession. Refs #1376 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…1376) Surface the new noticeBySession channel as a non-danger status box (role="status"/aria-live="polite") so a deadline-reached poll reads as a status, not a red error. Add role="alert"/aria-live="assertive" to the error box so an async outcome landing minutes after the click is announced to screen readers. After ~75s flip the spinner copy to "Still working… this may take a while.", kept alive across the poller handoff so it doesn't snap back to "Thinking…" while the turn is still in flight. Refs #1376 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a "long-turn resilience" describe block that stubs the turn POST
(sever / 502 / 429) and GET /sessions/{id} with server-truth fixtures
via page.route — no real Claude turn. Covers: severed-but-running
(spinner, no error), severed-but-succeeded (reply renders), genuine 502
(real error), severed-then-failed ("No reply came back"), pre-persistence
false-success guard, deadline -> neutral notice (via the
__TRINITY_SESSION_POLL_DEADLINE_MS__ test seam), T7 assistant-present-
AND-sentinel-still-set -> success not false "no reply", and T8 a 429
concurrent reject -> real error, never a silent reattach.
Refs #1376
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the severed-socket reconcile row to the session-tab failure-mode table, update the e2e and known-limitations sections to reflect the mostly-fixed long-turn behavior, and add the Recent Updates index row. Refs #1376 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AndriiPasternak31
marked this pull request as ready for review
June 29, 2026 22:48
5 tasks
vybe
approved these changes
Jun 30, 2026
vybe
left a comment
Contributor
There was a problem hiding this comment.
Validated via /validate-pr: Closes #1376, e2e T1–T8 regression cases name the issue, session-tab flow doc updated, CSO --diff clean, security scan clean. Reconciles severed long turns against server state — no false 'failed to send'. LGTM.
# Conflicts: # docs/memory/feature-flows.md
This was referenced Jun 30, 2026
pull Bot
pushed a commit
to bryanwills/trinity
that referenced
this pull request
Jul 9, 2026
…ost-release features Sync user docs with everything user-facing since the 2026-06-22 sync (123 commits, including the v0.7.0 release). All content code-derived. New pages: - whats-new/v0.7.0.md — user-facing release highlights (PostgreSQL for production + SQLite EOL 2026-09-01, Codex runtime, portable agent data, credential hot-reload, agent-isolation hardening) - advanced/voice-replies.md — canonical outbound-TTS page (epic Abilityai#24: Abilityai#25 Telegram, Abilityai#26 Slack, trinity-enterprise#56 WhatsApp) Major updates: - agent-sharing.md rewritten for the Access-tab/Sharing-tab split (trinity-enterprise#17/Abilityai#18/Abilityai#19/Abilityai#20): operator roster, Restricted↔Open, client roster, channel dialogs, public chat model (Abilityai#894), public-only custom instructions (Abilityai#1205) - setup.md: setup-token flow removed (trinity-enterprise#49), required admin email + email sign-in (Abilityai#82), opt-in intake (trinity-enterprise#38) - agent-chat.md / agent-session.md: unified Chat tab + Session-mode toggle (Abilityai#1112); severed-turn reconcile (Abilityai#1377) - deploy spokes: DATABASE_URL/Postgres path + SQLite EOL (Abilityai#300/Abilityai#1183/Abilityai#1278), pg_dump backup notes; fixes single-server.md's stale "not yet selectable" - whatsapp-integration.md: webhook must route to backend (Abilityai#1281), outbound media (Abilityai#1315) - mcp-server.md: tool catalog corrected to 93 tools; operator-queue respond (Abilityai#1104); dedicated chat_with_<slug> exposure (Abilityai#846) - smaller: Slack identity/icon/proactive (Abilityai#350, Abilityai#292), VoIP panel + persisted voice + Gacrux (trinity-enterprise#28), curated credential paths (Abilityai#1305/#11), key rotation (Abilityai#267), hot-reload rotation (Abilityai#1089), parallel-tasks ceiling (Abilityai#506), monitoring UI toggle (Abilityai#1409), JWT logout revocation (Abilityai#187), cancelled status (Abilityai#679), schedule scorecards (Abilityai#1115), Codex runtime (Abilityai#1187) Verification: whats-new codename/issue-number grep clean; enterprise-docs guard pattern clean; deploy-guide public-safety greps clean; all relative links resolve (4 pre-existing broken links fixed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the Session-mode false-failure (#1376): a long-running turn shows "Failed to send message" while the backend execution is still running and ultimately succeeds. The Session turn endpoint is synchronous, so an intermediary with a read timeout shorter than the axios ceiling (notably an external Cloudflare ~100s edge timeout) can sever the socket mid-turn — axios sees a network error and the
catchrendered an unconditional failure.This is the stay-on-page / proxy-timeout variant of the previously-fixed #759 (return-navigation variant). Frontend-only fix; no backend or schema change.
What changed
stores/sessions.js): on any send error,sendMessagenow reconciles againstGET /sessions/{id}before declaring failure.turn_in_progress=true→ hand off to the reattach poller (spinner stays, no error).startPolling): replaces theMAX_ATTEMPTS=60(~22 min) attempt count — unreliable under background-tab timer throttling — with a ~2h deadline covering the sentinel TTL. The deadline outcome routes through a neutral notice (noticeBySession), not a red error.SessionPanel.vue): neutral status box (role="status"),aria-liveon both error and notice so async outcomes are announced, and a "Still working…" spinner copy after ~75s kept alive across the poller handoff.e2e/session-tab.spec.js): T1–T8 stub the POST (sever / 502 / 429) and GET with server-truth fixtures — no real Claude turn./cso --diffdaily report — clean, no findings.Acceptance criteria
sendMessagechecksturn_in_progress/ latest assistant and reattaches instead of unconditionally settingerrorBySession.Closes #1376
🤖 Generated with Claude Code