diff --git a/artifacts/sleek-hermes-chat-mobile.png b/artifacts/sleek-hermes-chat-mobile.png index 40563f3..3f21684 100644 Binary files a/artifacts/sleek-hermes-chat-mobile.png and b/artifacts/sleek-hermes-chat-mobile.png differ diff --git a/src/domain.js b/src/domain.js index 4e5b42e..1eee576 100644 --- a/src/domain.js +++ b/src/domain.js @@ -4,7 +4,7 @@ const URGENT_TEXT_PATTERNS = Object.freeze([ ['blood', /\b(?:rectal bleeding|bleeding from (?:the )?(?:rectum|bottom)|blood(?:y)? (?:in|on|with) (?:my |the )?(?:stool|poop|bowel movement)|(?:stool|poop) (?:has|contains|with) blood)\b/i], ['blackOrDarkRed', /\b(?:(?:black|dark[- ]?red) (?:stool|poop|bowel movement)|(?:stool|poop|bowel movement) (?:is|looks?) (?:black|dark[- ]?red))s?\b/i], ['severePain', /\b(?:severe|constant|unrelenting) (?:abdominal|stomach|belly) pain\b/i], - ['vomiting', /\b(?:vomit(?:ing|ed)?|throwing up)\b/i], + ['vomiting', /\b(?:vomit(?:ing|ed|s)?|throw(?:ing|s)? up|threw up|thrown up)\b/i], ['fever', /\bfever(?:ish)?\b/i], ['cannotPassGas', /\b(?:cannot|can['’]?t|cant|unable to|not able to) pass gas\b/i], ]); diff --git a/tests/domain.test.js b/tests/domain.test.js index 8ac7646..975c080 100644 --- a/tests/domain.test.js +++ b/tests/domain.test.js @@ -50,6 +50,7 @@ test('detects common urgent symptom language without matching unrelated blood wo 'My stool is black', 'I have severe stomach pain', 'I am throwing up and have a fever', + 'I threw up', 'I am unable to pass gas', ]) assert.equal(detectUrgentText(message).urgent, true, message); assert.equal(detectUrgentText('My blood pressure was checked').urgent, false); diff --git a/tests/hermes-agent-service.test.js b/tests/hermes-agent-service.test.js index 75d215e..c8470c3 100644 --- a/tests/hermes-agent-service.test.js +++ b/tests/hermes-agent-service.test.js @@ -128,6 +128,7 @@ test('authoritative chat service intercepts urgent message and ledger symptoms b await service.unlock({ origin, accessCode: 'test-agent-access-code-2026' }); const messageResult = await service.chat({ origin, cookieToken: 'safety-cookie', payload: { message: 'I have rectal bleeding', ledger: [] } }); + const pastTenseVomitingResult = await service.chat({ origin, cookieToken: 'safety-cookie', payload: { message: 'I threw up', ledger: [] } }); const ledgerResult = await service.chat({ origin, cookieToken: 'safety-cookie', payload: { message: 'What does my journal show?', ledger: [{ bristolType: 4, color: 'brown', note: '', symptoms: { cannotPassGas: true } }], @@ -138,7 +139,7 @@ test('authoritative chat service intercepts urgent message and ledger symptoms b } }); assert.equal(calls.length, 0); - for (const result of [messageResult, ledgerResult, noteResult]) { + for (const result of [messageResult, pastTenseVomitingResult, ledgerResult, noteResult]) { assert.equal(result.safetyOverride, true); assert.match(result.reply, /medical help/i); assert.doesNotMatch(result.reply, /unsafe upstream/i); diff --git a/tests/sleek-chat.acceptance.mjs b/tests/sleek-chat.acceptance.mjs index c3c2e07..3c19626 100644 --- a/tests/sleek-chat.acceptance.mjs +++ b/tests/sleek-chat.acceptance.mjs @@ -38,7 +38,7 @@ assert.equal(chatRequest.message, 'What pattern do you see?'); assert.ok(Array.isArray(chatRequest.ledger)); assert.equal(JSON.stringify(chatRequest).includes('photoDataUrl'), false, 'photos never enter chat context'); const previousRequest = chatRequest; -await page.locator('#chat-message').fill('I am unable to pass gas'); +await page.locator('#chat-message').fill('I threw up'); await page.locator('#send-chat').click(); await page.waitForSelector('.bubble.timmy >> text=Pause and get medical help'); assert.equal(chatRequest, previousRequest, 'urgent language must be intercepted before the Hermes request');