From c91511509655980294025fcbbb0efc0b9b72920a Mon Sep 17 00:00:00 2001 From: claude Date: Tue, 4 Aug 2026 02:58:19 +0400 Subject: [PATCH] =?UTF-8?q?eval:=20a=20verb=20governed=20by=20"=D1=82?= =?UTF-8?q?=D1=8B"=20is=20his,=20not=20her=20drift=20(V-462)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CheckFeminine flagged "ты заплатил за домен" as a masculine self-reference. The second pass reads a masculine past-tense verb before "тебе", "тебя" or "за" as her speaking with the pronoun dropped, and it checked neither the subject nor what "за" pointed at. He is male, so a verb governed by "ты" must be masculine, and "за домен" is a price rather than a favour. The talk fixture was under-reporting by a point whenever a reply addressed him in the past tense, which is common. --- internal/phraser/eval/checks.go | 31 ++++++++++++++++++++++++++++-- internal/phraser/eval/eval_test.go | 6 ++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/internal/phraser/eval/checks.go b/internal/phraser/eval/checks.go index 4fffc46..250593b 100644 --- a/internal/phraser/eval/checks.go +++ b/internal/phraser/eval/checks.go @@ -173,12 +173,23 @@ func checkFeminine(body string) Result { // Second pass: self-reference with the pronoun dropped — "напомнил тебе", // "проверил за тебя". A masculine past-tense verb whose object is HIM can // only be her speaking about herself. + // + // Two guards, both from a false positive on the talk fixture: "ты заплатил + // за домен до марта" scored as her drift and cost the run a point it had + // earned (Vikunja #462). He is male, so a past-tense verb governed by "ты" + // must be masculine. And a bare "за" is not evidence of anything — "за + // домен" is a price, "за тебя" is her doing something on his behalf — so it + // only counts when he is the one it points at. for i, w := range words { - if !masculinePast(w) || i+1 >= len(words) { + if !masculinePast(w) || i+1 >= len(words) || governedByYou(words, i) { continue } next := words[i+1] - if next == "тебе" || next == "тебя" || next == "за" { + aboutHim := next == "тебе" || next == "тебя" + if next == "за" && i+2 < len(words) && (words[i+2] == "тебя" || words[i+2] == "тебе") { + aboutHim = true + } + if aboutHim { return Result{CheckFeminine, false, fmt.Sprintf("masculine self-reference %q before %q", w, next)} } @@ -652,3 +663,19 @@ func checkEllipsis(body string) Result { } return Result{CheckEllipsis, true, ""} } + +// governedByYou reports whether "ты" stands close enough in front of the verb +// at index i to be its subject. Three words, the same window checkFeminine's +// first pass uses after "я", and it stops at a first-person pronoun so "ты +// просил, я напомнил" still trips. +func governedByYou(words []string, i int) bool { + for j := i - 1; j >= 0 && j >= i-3; j-- { + switch words[j] { + case "ты": + return true + case "я": + return false + } + } + return false +} diff --git a/internal/phraser/eval/eval_test.go b/internal/phraser/eval/eval_test.go index 3342793..150f12b 100644 --- a/internal/phraser/eval/eval_test.go +++ b/internal/phraser/eval/eval_test.go @@ -106,6 +106,12 @@ func TestChecksCatchWhatTheyClaim(t *testing.T) { {"masculine predicative", "я должен сказать: попей воды.", CheckFeminine}, // The other direction: HE is male, so second-person masculine is right. {"second person masculine ok", "ты не пил воду четыре часа.", ""}, + // The recorded false positive: "заплатил" sits before "за", and the + // second pass read that as her dropping the pronoun. The subject is + // "ты" and he is male, so the reply is right (Vikunja #462). + {"second person masculine before за", "ты заплатил за домен до марта, а воду пить всё равно надо.", ""}, + // The same shape she really does get wrong still trips. + {"masculine on his behalf", "проверил за тебя — воды не было четыре часа.", CheckFeminine}, // The real observed failure: she addressed him as a woman. {"feminine second person", "ты давно не отдыхала — попей воды.", CheckHisGender}, {"feminine second person no dash", "ты пила воду четыре часа назад.", CheckHisGender}, -- 2.52.0