diff --git a/internal/phraser/eval/address_time_test.go b/internal/phraser/eval/address_time_test.go new file mode 100644 index 0000000..894a05c --- /dev/null +++ b/internal/phraser/eval/address_time_test.go @@ -0,0 +1,26 @@ +package eval + +import "testing" + +func TestAddressTimeWordDoesNotBlind(t *testing.T) { + // A nudge that opens with a time word must still be caught. Without the + // time words in the stoplist, "сегодня" was read as the third party. + for _, s := range []string{ + "сегодня он не ел 11 дней", + "вчера он не пил воду", + "опять он забыл про таблетки", + } { + if r := checkAddress(s); r.Pass { + t.Errorf("checkAddress(%q) passed, want a third-person failure", s) + } + } + // Still must not fire when a third party really is named. + for _, s := range []string{ + "сегодня сервис упал, он не отвечает", + "ты не пил воду четыре часа", + } { + if r := checkAddress(s); !r.Pass { + t.Errorf("checkAddress(%q) failed: %s", s, r.Detail) + } + } +} diff --git a/internal/phraser/eval/checks.go b/internal/phraser/eval/checks.go index 3a90ffe..838cbd3 100644 --- a/internal/phraser/eval/checks.go +++ b/internal/phraser/eval/checks.go @@ -340,7 +340,11 @@ func prevWord(words []string, i int) string { // - it only looks BACKWARD. "Он не отвечает, сервис упал" names the subject // after the pronoun and is flagged wrongly. // - any noun earlier in the message counts as an antecedent, even when it is -// not one ("после обеда он не ел" reads as legitimate and is missed). +// not one ("после обеда он не ел" reads as legitimate and is missed). The +// common time words are stoplisted so the usual nudge opening does not +// blind it, but a message with any other noun in front still slips through. +// This is the check's real hole; widening it further would start flagging +// legitimate third-party messages, so it stops here. // - a message that opens with "ты" and only later slips into "он" is missed, // because "ты" itself is skipped but the words around it are not. // - formal address outside these endings (short adjectives, "вашими" style @@ -392,6 +396,12 @@ var notAnAntecedent = map[string]bool{ "ещё": true, "еще": true, "тоже": true, "там": true, "тут": true, "здесь": true, "это": true, "что": true, "как": true, "когда": true, "чтобы": true, "потому": true, "сейчас": true, "потом": true, + // Time words. A nudge almost always opens with one ("сегодня он не ел"), + // and without them the very next word is read as the person being talked + // about, so the check misses the exact break it was written for. + "сегодня": true, "вчера": true, "завтра": true, "послезавтра": true, + "утром": true, "днём": true, "днем": true, "вечером": true, "ночью": true, + "опять": true, "снова": true, "весь": true, "всю": true, "целый": true, "я": true, "мне": true, "меня": true, "мной": true, "мы": true, "нас": true, "ты": true, "тебя": true, "тебе": true, "тобой": true, "твой": true, "твоя": true, "твоё": true, "твое": true, "твои": true, "твою": true,