fix: recognize past-tense vomiting in chat safety
All checks were successful
Quality gates / quality (pull_request) Successful in 1m20s

This commit is contained in:
Timmy 2026-08-20 16:57:09 +00:00
parent cc1fc6ee36
commit 1935ecc345
5 changed files with 5 additions and 3 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 311 KiB

View File

@ -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],
]);

View File

@ -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);

View File

@ -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);

View File

@ -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');