fix: set QA latch on user_message path#7424
Conversation
The QA latch was only set in handleTaskSubmit and wireEscalationHandler, so user messages sent via the user_message path (handleUserMessage in sessions.ts) never detected QA intent. This meant if a user typed "help me test Slack typing" as a regular chat message, the latch would not be active when the agent later escalated to CU. Add detectQaIntent/detectQaOptOut checks to handleUserMessage so the latch is set/cleared before the message is processed, ensuring subsequent CU escalations correctly inherit QA mode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 24f1fc1379
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const messageContent = msg.content ?? ''; | ||
| if (messageContent) { | ||
| if (detectQaOptOut(messageContent)) { | ||
| clearQaLatch(msg.sessionId); | ||
| } else if (detectQaIntent(messageContent)) { | ||
| setQaLatch(msg.sessionId); |
There was a problem hiding this comment.
Defer QA latch updates until message is accepted
Updating the latch here mutates conversation state before the message is actually accepted, but this handler can still return early on secret blocking (checkIngressForSecrets) or queue rejection (result.rejected). In those cases a rejected user_message containing QA/opt-out phrases still sets or clears the latch, so later unrelated escalations in the same session can incorrectly flip qaMode/requiresRecording even though the triggering message never ran.
Useful? React with 👍 / 👎.
Move QA intent/opt-out detection in handleUserMessage to after the secret-ingress and queue-rejection checks. Previously, the latch was mutated before those guards, so a message blocked by checkIngressForSecrets or rejected by enqueueMessage would still flip the QA latch — causing incorrect qaMode/requiresRecording state for subsequent escalations. Also adds two contract tests documenting the invariant that rejected and blocked messages must not mutate the latch. Addresses review feedback from #7424. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move QA intent/opt-out detection in handleUserMessage to after the secret-ingress and queue-rejection checks. Previously, the latch was mutated before those guards, so a message blocked by checkIngressForSecrets or rejected by enqueueMessage would still flip the QA latch — causing incorrect qaMode/requiresRecording state for subsequent escalations. Also adds two contract tests documenting the invariant that rejected and blocked messages must not mutate the latch. Addresses review feedback from #7424. Co-authored-by: Vellum Assistant <assistant@vellum.ai> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
Addressed in #7459 |
Summary
detectQaIntent/detectQaOptOutchecks tohandleUserMessageinsessions.tsso the QA latch is set/cleared when users send regular chat messages (not justtask_submit)user_messagewould not activate QA mode for subsequent CU escalationsTest plan
bun test src/__tests__/qa-latch-user-message.test.ts— 6 tests passbunx tsc --noEmit— no new type errors (pre-existing errors in unrelated files only)🤖 Generated with Claude Code