Fix WebChat dispatch failure session status#84352
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 22, 2026, 8:23 AM ET / 12:23 UTC. Summary PR surface: Source +65, Tests +67. Total +132 across 2 files. Reproducibility: yes. at source level: current main's Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land a final head that keeps this failed-session lifecycle persistence, preserves the abort/error ordering from #91000 or rebases after it, and clears focused Gateway/session lifecycle validation. Do we have a high-confidence way to reproduce the issue? Yes, at source level: current main's Is this the best way to solve the issue? Mostly yes for the narrow WebChat pre-agent dispatch rejection case: the owner path is the AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against fcb4c5d0416a. Label changesLabel justifications:
Evidence reviewedPR surface: Source +65, Tests +67. Total +132 across 2 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
ClawSweeper PR egg ✨ Hatched: 🥚 common Tiny Signal Puff Hatch commandComment Hatchability rules:
Rarity: 🥚 common. What is this egg doing here?
|
There was a problem hiding this comment.
Pull request overview
This PR fixes a WebChat failure-mode where chat.send dispatch rejection could leave the persisted session lifecycle state stuck as status: "running" even though the active run was already cleaned up, causing the Control UI to remain in a running state indefinitely.
Changes:
- Persist a terminal
"error"lifecycle event onchat.senddispatch rejection so the session store updates tostatus: "failed"with end timestamps. - Broadcast a
sessions.changedevent on this error path withstatus: "failed"andhasActiveRun: false. - Add a regression test asserting
sessions.listreturnsstatus: "failed"andhasActiveRun: falseafter a pre-reply dispatch rejection.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/gateway/server-methods/chat.ts | Persists a terminal lifecycle error and broadcasts sessions.changed when WebChat dispatch rejects before a reply. |
| src/gateway/server.chat.gateway-server-chat.test.ts | Adds regression coverage for sessions transitioning from running → failed when dispatch rejects before reply. |
| phase: "error", | ||
| startedAt: lifecycleStartedAt, | ||
| endedAt, | ||
| error: String(err), |
88bdd2c to
58a1c5d
Compare
Dependency graph guard clearedThis PR no longer has blocked dependency graph changes. A future dependency graph change requires a fresh
|
278af87 to
e0e6169
Compare
|
Merged via squash.
Thanks @jesse-merhi! |
Summary
WebChat dispatch failures before an agent run starts now close the persisted session lifecycle instead of leaving the session stuck as running. The gateway already broadcast a chat error and removed active-run tracking; this PR adds the missing terminal session lifecycle write and
sessions.changednotification sosessions.listand Control UI consumers seestatus: "failed"withhasActiveRun: false.The current net diff is limited to
src/gateway/server-methods/chat.tsandsrc/gateway/server.chat.gateway-server-chat.test.ts.What Changed
chat.sendnow records a pending lifecycle error only when dispatch rejects beforeagentRunStarted, the run was not explicitly aborted, and the run is not inchatAbortedRuns.phase: "error"when no active run remains for the session.sessions.changedwith reasonchat.dispatch-errorso session subscribers receive the failed terminal state.dispatchInboundMessage, waits for the chat error andsessions.changed, and verifies both the event andsessions.listreportstatus: "failed"andhasActiveRun: false.Flow
flowchart TD A["WebChat chat.send starts"] --> B["dispatchInboundMessage rejects before agent run starts"] B --> C["Broadcast chat error"] C --> D["Clean active run tracking"] D --> E{"Any active run still tracked for session?"} E -- "yes" --> F["Leave session lifecycle unchanged"] E -- "no" --> G["Persist lifecycle phase: error"] G --> H["Emit sessions.changed with failed status"]Proof
Behavioral proof:
running.{ "type": "event", "event": "sessions.changed", "payload": { "reason": "chat.dispatch-error", "sessionKey": "agent:main:main", "sessionId": "sess-main", "status": "failed", "hasActiveRun": false } }sessions.listcall returns the same terminal shape for the affected session:status: "failed",hasActiveRun: false, and populatedstartedAt,endedAt, andruntimeMsfields.Screenshots
No screenshots are included. This PR changes backend gateway session lifecycle persistence and event payloads, not Control UI layout or visible components; the reviewer-visible behavior is better proven by the
sessions.changedpayload andsessions.liststate asserted by the regression test. A screenshot would only show unchanged UI consuming the fixed gateway state.Verification
Reviewer-checkable behavior:
src/gateway/server.chat.gateway-server-chat.test.tsincludesmarks a running webchat session failed when dispatch rejects before a reply, which simulates the dispatch rejection and asserts the event and list-state behavior above.mmdcbefore posting.Automated checks:
pr_net_diff.py --markdownshowed only two net changed files and no branch-only churn.node scripts/run-vitest.mjs src/gateway/server.chat.gateway-server-chat.test.ts -t "marks a running webchat session failed when dispatch rejects before a reply"passed on headc702c8b59b7.node scripts/run-vitest.mjs src/gateway/server.chat.gateway-server-chat.test.tspassed on headc702c8b59b7with 72 tests.pnpm exec oxfmt --check src/gateway/server-methods/chat.ts src/gateway/server.chat.gateway-server-chat.test.tspassed.node scripts/run-oxlint.mjs src/gateway/server-methods/chat.tspassed.pnpm tsgo:test:srcpassed.git diff --checkpassed.28010707174passed on headc702c8b59b7, includingcheck-lint,check-test-types, andchecks-node-compact-small-5.Not run: