Skip to content

fix(exam-checker): casual mention no longer hijacks chat; always give an exit (bd-2484) - #142

Open
mah-noor1 wants to merge 1 commit into
developfrom
bd-2484-exam-checker-escape
Open

fix(exam-checker): casual mention no longer hijacks chat; always give an exit (bd-2484)#142
mah-noor1 wants to merge 1 commit into
developfrom
bd-2484-exam-checker-escape

Conversation

@mah-noor1

Copy link
Copy Markdown
Collaborator

The bug

A plain-text question — "Can you grade exam papers for me?" — silently started a real exam-grading session, then captured every following plain-text message so normal chat stopped working. Only slash commands escaped, and there was no timeout and no way to type your way out.

Two stacked faults, both confirmed from source (not the report):

  1. Trigger too loose. shouldTriggerExamChecker matched a keyword anywhere in the text via .includes(), so "grade exam" buried inside a question started the feature.
  2. No way out. handleExamCancel was dead code (never wired). A slash command bypassed the checker but left the session active in Supabase (which persists indefinitely — the 24h Redis TTL just re-hydrates from the DB), so the next plain text was recaptured. This is the exact trap already fixed for coaching in bd-2508 ("held for 269 hours").

The fix

  • Anchored trigger — the message must be or lead with a trigger phrase, not merely contain one. "grade exams" still starts it; a question that mentions grading does not.
  • Explicit exitstop / cancel / exit (+ Urdu/Arabic) ends the session and confirms it; any slash command ends it silently then runs (mirrors the bd-2508 coaching fix — bypassing without ending lets the next message get recaptured).
  • Auto-expiry (defense-in-depth) — an accidental session (collecting_images, zero images, untouched > 1h) auto-expires so it can't linger. Never touches a grading that's actually in progress.

Files

File Change
bot/shared/handlers/exam-checker.handler.js anchored shouldTriggerExamChecker; new isExamExitText + endActiveExamSession; handleExamCancel now delegates
bot/shared/handlers/text-message.handler.js escape-path block before exam detection: exit word ends+returns, slash ends+falls-through
bot/shared/services/exam-checker/exam-session.service.js _isStaleCollectingSession + _expireIfStale, wired into getActive

Tests (TDD, red-first)

2 new suites, 14 tests, each written to fail against current code first:

  • tests/exam-checker/bd-2484-trigger-and-exit.test.js
  • tests/exam-checker/bd-2484-session-staleness.test.js

Full npm test: 44 failing suites at baseline == 44 after (all pre-existing environmental dotenv/dep failures in a fresh checkout), +14 passing, zero new failures.

Not covered here / follow-ups

  • No menu button/command entry point for exam-checking exists today — natural-language commands remain the only way to start it. A deterministic button entry is a reasonable future hardening.
  • A stuck user's existing session from before this deploy is cleared the moment they type any slash command or stop (or after 1h) once this is live.

🤖 Generated with Claude Code

…an exit

A plain-text question — "Can you grade exam papers for me?" — silently
started a real exam-grading session because shouldTriggerExamChecker matched
the phrase "grade exam" ANYWHERE via .includes(). Once in that session every
subsequent plain-text message was captured with no reply, and there was no
timeout and no text way out (handleExamCancel was dead code, and a slash
command bypassed the checker but left the session active, so the next message
was recaptured — the same trap fixed for coaching in bd-2508).

Fixes, all TDD (red-first, 14 new tests):
- Anchored trigger: the message must BE or LEAD with a trigger phrase, not
  merely contain one. "grade exams" still starts it; a question mentioning it
  does not.
- Explicit exit words (stop/cancel/exit + Urdu/Arabic) end the session and
  confirm; a slash command ends it silently then runs (mirrors bd-2508).
- Accidental sessions (collecting_images, zero images, untouched >1h) auto-
  expire so they cannot linger and recapture chat.

Baseline suite unchanged (44 pre-existing env failures before and after);
+14 passing tests. Refs: bd-2484

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mah-noor1
mah-noor1 changed the base branch from main to develop August 7, 2026 05:59
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