c259ed6c73
Step 4 of the board build (docs/plans/15-board-surface.md). Naming a task instead of its position reached nothing: "закрой задачу купить молоко" routed act, found no allowlisted fn, and the gate asked "Что сделать?". The position path already worked through resolveCandidate, but only in the two turns after she read the list out. TaskStatusGrammar is the same shape TaskCaptureGrammar uses — matches broadly, decides in Build, no eighth intent — and fills the fn slot with task_status, which is neither a Hexis capability nor a Praxis one. Three conditions, all required: the board noun, so no ordinary sentence claims a turn; exactly one status class, since "готово, убери" names two and asking beats picking; and a status word matched as an imperative exactly or a stative by lemma. So a bare "готово" and a bare "закрой" are not this rule's, and the second belongs to Praxis, which claims it already. Two lexicon sets rather than one with a value. The store records which of the two transitions happened and /tasks shows it: work he chose to stop is not work he did. Measured on the fixture, two new cases (ru-act-020, ru-act-021). Classifier + ONNX 62/89 (69.7%) → 64/91 (70.3%); cascade+llm 67/89 (75.3%) → 69/91 (75.8%, 80.2% intent-only) at p50 1.225s. Both new cases claimed at stage 0, no case regressed, clarify counts unchanged at 3 false / 1 missed. The task's own warning stands: every such grammar runs its parser ahead of the resident model on every turn, so this is the last one that is free. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SoL7EBdYC5Mhz3DJd49GJy
203 lines
16 KiB
JSON
203 lines
16 KiB
JSON
{
|
||
"schema_version": 1,
|
||
"name": "russian closed-class lexicons v1",
|
||
"notes": [
|
||
"Every set here is a CLOSED CLASS: the language has a fixed number of members and the list can be finished. That is why it is a list at all. A word list that can never be finished is a guess dressed as a rule, and it belongs with the embedder, not here (Vikunja #522).",
|
||
"Editing a word is a data change. No Go change, no rebuild of a pattern, no second copy to keep in step — month names used to live in two files and day offsets in three.",
|
||
"Interrogatives and capture verbs carry their English members too. He speaks both languages in one sentence and the router sees one utterance.",
|
||
"The sets are matched over tokens, never as substrings: \"что\" inside \"чтобы\" and \"как\" inside \"какао\" are not questions.",
|
||
"Order matters in weekdays, months and hours, and nowhere else. weekdays starts at Sunday because Go's time.Weekday does. months is 1-indexed with an empty slot at 0 for the same reason. hours is indexed by the hour itself.",
|
||
"A form missing from a closed set is a bug report, not a judgement call. Add it."
|
||
],
|
||
"sets": {
|
||
"interrogatives": {
|
||
"note": "The Russian interrogative pronouns and adverbs, declined, plus the English ones. Closed class: this is the whole list, and a question word outside it does not exist.",
|
||
"words": [
|
||
"что", "чего", "чему", "чем", "чём",
|
||
"кто", "кого", "кому", "кем", "ком",
|
||
"какой", "какая", "какое", "какие", "какого", "какому", "каким", "каких", "какими", "каком",
|
||
"который", "которая", "которое", "которые", "которого", "котором",
|
||
"чей", "чья", "чьё", "чьи",
|
||
"где", "куда", "откуда", "когда", "докуда",
|
||
"почему", "зачем", "отчего", "как", "сколько", "насколько", "каково",
|
||
"what", "who", "whom", "whose", "why", "when", "where", "which", "how"
|
||
]
|
||
},
|
||
"capture_verbs": {
|
||
"note": "An explicit instruction to record something, in the imperative he actually speaks. Not a closed class in the grammatical sense, but a closed set of the commands Maven answers to — it is her vocabulary, and its members are decided here rather than discovered.",
|
||
"words": [
|
||
"запиши", "запомни", "отметь", "заметь", "добавь", "сохрани", "занеси", "внеси",
|
||
"note", "remember", "log", "save", "add"
|
||
]
|
||
},
|
||
"narrative_requests": {
|
||
"note": "\"Tell me about X\" asks for knowledge Maven does not hold about him. It carries no question mark and no interrogative, which is how \"расскажи про битву при Ватерлоо\" reached the fact store (#470).",
|
||
"words": [
|
||
"расскажи", "объясни", "опиши", "перечисли", "поясни",
|
||
"tell", "explain", "describe", "list"
|
||
]
|
||
},
|
||
"ordinals": {
|
||
"note": "Position words, as spoken, with the gender and oblique forms Russian requires: \"отметь второй пункт\" and \"закрепи вторым\" name one position (Vikunja #516). Values are the 1-based position, and -1 is the last one, which is a position rather than a count. The genitive forms here are also what a half-past hour needs (\"в половине восьмого\", V-538), so this set is written for two callers. It runs to twelve rather than ten because a clock does: \"в половине двенадцатого\" is 11:30.",
|
||
"values": {
|
||
"первый": 1, "первая": 1, "первое": 1, "первого": 1, "первую": 1, "первым": 1, "первой": 1, "first": 1,
|
||
"второй": 2, "вторая": 2, "второе": 2, "второго": 2, "вторую": 2, "вторым": 2, "second": 2,
|
||
"третий": 3, "третья": 3, "третье": 3, "третьего": 3, "третью": 3, "третьим": 3, "третьей": 3, "third": 3,
|
||
"четвёртый": 4, "четвертый": 4, "четвёртая": 4, "четвертая": 4, "четвёртого": 4, "четвертого": 4, "четвёртую": 4, "четвертую": 4, "четвёртым": 4, "четвертым": 4, "fourth": 4,
|
||
"пятый": 5, "пятая": 5, "пятое": 5, "пятого": 5, "пятую": 5, "пятым": 5, "пятой": 5, "fifth": 5,
|
||
"шестой": 6, "шестая": 6, "шестое": 6, "шестого": 6, "шестую": 6, "шестым": 6, "sixth": 6,
|
||
"седьмой": 7, "седьмая": 7, "седьмое": 7, "седьмого": 7, "седьмую": 7, "седьмым": 7, "seventh": 7,
|
||
"восьмой": 8, "восьмая": 8, "восьмое": 8, "восьмого": 8, "восьмую": 8, "восьмым": 8, "eighth": 8,
|
||
"девятый": 9, "девятая": 9, "девятое": 9, "девятого": 9, "девятую": 9, "девятым": 9, "ninth": 9,
|
||
"десятый": 10, "десятая": 10, "десятое": 10, "десятого": 10, "десятую": 10, "десятым": 10, "tenth": 10,
|
||
"одиннадцатый": 11, "одиннадцатая": 11, "одиннадцатое": 11, "одиннадцатого": 11, "одиннадцатую": 11, "одиннадцатым": 11, "eleventh": 11,
|
||
"двенадцатый": 12, "двенадцатая": 12, "двенадцатое": 12, "двенадцатого": 12, "двенадцатую": 12, "двенадцатым": 12, "twelfth": 12,
|
||
"последний": -1, "последняя": -1, "последнее": -1, "последнего": -1, "последнюю": -1, "последним": -1, "last": -1
|
||
}
|
||
},
|
||
"cardinals": {
|
||
"note": "Number words as spoken, with the gender variants Russian requires (один/одна/одно and два/две agree with the noun that follows) and the oblique forms, because a spoken time declines: \"в семь\", \"к семи\", \"около семи\" are three forms of one hour (Vikunja #530). Values are the number itself. Twenties and up are compounds and are read as their parts, so only the round members are listed.",
|
||
"values": {
|
||
"ноль": 0, "нуль": 0, "zero": 0,
|
||
"один": 1, "одна": 1, "одно": 1, "одного": 1, "одной": 1, "одну": 1, "one": 1,
|
||
"два": 2, "две": 2, "двух": 2, "two": 2,
|
||
"три": 3, "трёх": 3, "трех": 3, "three": 3,
|
||
"четыре": 4, "четырёх": 4, "четырех": 4, "four": 4,
|
||
"пять": 5, "пяти": 5, "five": 5,
|
||
"шесть": 6, "шести": 6, "six": 6,
|
||
"семь": 7, "семи": 7, "seven": 7,
|
||
"восемь": 8, "восьми": 8, "eight": 8,
|
||
"девять": 9, "девяти": 9, "nine": 9,
|
||
"десять": 10, "десяти": 10, "ten": 10,
|
||
"одиннадцать": 11, "одиннадцати": 11, "eleven": 11,
|
||
"двенадцать": 12, "двенадцати": 12, "twelve": 12,
|
||
"тринадцать": 13, "тринадцати": 13, "thirteen": 13,
|
||
"четырнадцать": 14, "четырнадцати": 14, "fourteen": 14,
|
||
"пятнадцать": 15, "пятнадцати": 15, "fifteen": 15,
|
||
"шестнадцать": 16, "шестнадцати": 16, "sixteen": 16,
|
||
"семнадцать": 17, "семнадцати": 17, "seventeen": 17,
|
||
"восемнадцать": 18, "восемнадцати": 18, "eighteen": 18,
|
||
"девятнадцать": 19, "девятнадцати": 19, "nineteen": 19,
|
||
"двадцать": 20, "двадцати": 20, "twenty": 20,
|
||
"тридцать": 30, "тридцати": 30, "thirty": 30,
|
||
"сорок": 40, "сорока": 40, "forty": 40,
|
||
"пятьдесят": 50, "пятидесяти": 50, "fifty": 50,
|
||
"шестьдесят": 60, "шестидесяти": 60, "sixty": 60,
|
||
"семьдесят": 70, "семидесяти": 70, "seventy": 70,
|
||
"восемьдесят": 80, "восьмидесяти": 80, "eighty": 80,
|
||
"девяносто": 90, "девяноста": 90, "ninety": 90,
|
||
"сто": 100, "ста": 100, "hundred": 100
|
||
}
|
||
},
|
||
"day_offsets": {
|
||
"note": "The words that name a day relative to today, and the number of days each one moves. Only explicit ones: an offset is a claim about which day, and guessing which day is the guess these callers refuse to make. Multi-word members are matched as a phrase.",
|
||
"values": {
|
||
"позавчера": -2,
|
||
"вчера": -1,
|
||
"yesterday": -1,
|
||
"сегодня": 0,
|
||
"today": 0,
|
||
"tonight": 0,
|
||
"завтра": 1,
|
||
"tomorrow": 1,
|
||
"послезавтра": 2,
|
||
"day after tomorrow": 2
|
||
}
|
||
},
|
||
"weekdays": {
|
||
"note": "Nominative, starting at Sunday so the index is Go's time.Weekday.",
|
||
"words": [
|
||
"воскресенье", "понедельник", "вторник", "среда",
|
||
"четверг", "пятница", "суббота"
|
||
]
|
||
},
|
||
"months_genitive": {
|
||
"note": "The form a date takes: \"10 июля\", not \"июль\". 1-indexed, so slot 0 is empty and month numbers need no arithmetic.",
|
||
"words": [
|
||
"", "января", "февраля", "марта", "апреля", "мая", "июня",
|
||
"июля", "августа", "сентября", "октября", "ноября", "декабря"
|
||
]
|
||
},
|
||
"hours_spoken": {
|
||
"note": "Hours spelled out for the voice: \"3 ч\" is fine on a screen and wrong out loud. Indexed by the hour, 0 to 23.",
|
||
"words": [
|
||
"ноль", "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь",
|
||
"девять", "десять", "одиннадцать", "двенадцать", "тринадцать",
|
||
"четырнадцать", "пятнадцать", "шестнадцать", "семнадцать", "восемнадцать",
|
||
"девятнадцать", "двадцать", "двадцать один", "двадцать два", "двадцать три"
|
||
]
|
||
},
|
||
"repair_markers": {
|
||
"note": "The ways he says she got it wrong. A closed set of Maven's own vocabulary, like capture_verbs: its members are decided here rather than discovered. NOT the embedder, and that is deliberate — a correction rewrites the previous turn and runs pre-route, before the turn vector exists, so a near-miss would redo a request he did not make. Phrases, matched as substrings.",
|
||
"words": [
|
||
"не так поняла", "неправильно поняла", "ты не поняла", "не поняла меня",
|
||
"ты ошиблась", "это не", "а не", "не про то",
|
||
"got it wrong", "not a ", "that was wrong"
|
||
]
|
||
},
|
||
"first_person": {
|
||
"note": "Every form of the first-person pronoun, plus the English ones. Closed class in the strictest sense: the language has these and no others. A sentence carrying one is about him, which is what makes it a fact rather than a passing complaint.",
|
||
"words": [
|
||
"я", "меня", "мне", "мной", "мною",
|
||
"мы", "нас", "нам", "нами",
|
||
"i", "me", "my", "mine", "we", "us", "our"
|
||
]
|
||
},
|
||
"not_place_after_v": {
|
||
"note": "Words that follow the preposition \"в\" without naming a place, so \"в общем\" and \"в котором часу\" are not read as a city we do not know.",
|
||
"words": [
|
||
"данный", "данную", "данное", "этот", "эту", "это", "том", "той",
|
||
"котором", "которой", "какое", "какой", "который", "каком",
|
||
"общем", "точности", "курсе", "принципе", "итоге", "целом",
|
||
"сутках", "часах", "минутах", "секундах", "неделе", "месяце", "году",
|
||
"начале", "конце", "середине", "течение", "течении"
|
||
]
|
||
},
|
||
"parts_of_day": {
|
||
"note": "The times of day named as one word, in the instrumental case Russian uses for when something happens. A day has as many parts as it has, so this set is finished. They are not day offsets: \"вечером\" says which part of a day, never which day (Vikunja #530).",
|
||
"words": [
|
||
"утром", "днём", "днем", "вечером", "ночью",
|
||
"morning", "afternoon", "evening", "night"
|
||
]
|
||
},
|
||
"reminder_verbs": {
|
||
"note": "The imperatives that mean \"remind me\", in the forms he speaks. The same kind of set as capture_verbs and decided the same way: it is her vocabulary, not a discovery about Russian (Vikunja #530).",
|
||
"words": [
|
||
"напомни", "напомните", "напомнить", "напоминай",
|
||
"remind"
|
||
]
|
||
},
|
||
"half_hour": {
|
||
"note": "The forms of \"половина\" that introduce a spoken half hour: \"в половине восьмого\", \"к половине\", the bare \"пол\" of \"полвосьмого\". The set matters to two callers and for opposite reasons (V-522). The clock rewrite reads the ordinal after one of these as the hour being entered, and the ordinal-selection turn has to REFUSE that ordinal, because \"в половине восьмого\" names a time and not the eighth thing she read out.",
|
||
"words": [
|
||
"половина", "половине", "половину", "половины", "пол",
|
||
"half"
|
||
]
|
||
},
|
||
"filler_particles": {
|
||
"note": "Words that carry no subject of their own: particles, the politeness words, and the first-person object he addresses her with. A caller asking \"did he say WHAT to remind him about\" has to discount these, or \"ну напомни же\" and \"напомни мне пожалуйста\" both read as a reminder whose subject is the particle. Closed in the sense that matters: these are function words, and the language is not adding any. Not a stopword list — a stopword list is a scoring convenience and may be as long as it likes, while every word here has to be one that cannot BE a reminder's subject.",
|
||
"words": [
|
||
"ну", "же", "уж", "там", "вот", "пожалуйста", "плиз", "ка",
|
||
"давай", "давай-ка", "а", "и", "бы", "мне", "меня", "мной",
|
||
"please", "just", "hey", "me"
|
||
]
|
||
},
|
||
"task_done_words": {
|
||
"note": "The ways he says a task is finished, split by mood the way the Praxis lifecycle words are (Vikunja #512). The imperatives are addressed to her and are matched exactly, because morph.SameWord makes \"закрой\" and \"закрыл\" one word and only one of them is an instruction. The statives report his own day and are matched by lemma, since \"сделано\", \"сделана\" and \"сделанную\" are one state. Closed because these are her vocabulary for one transition, not a discovery about Russian.",
|
||
"words": [
|
||
"закрой", "закройте", "закрыть", "заверши", "завершить", "close", "finish",
|
||
"сделано", "сделал", "сделала", "выполнено", "выполнил", "выполнила",
|
||
"готово", "готова", "закрыл", "закрыла", "done", "finished"
|
||
]
|
||
},
|
||
"task_drop_words": {
|
||
"note": "The ways he abandons a task rather than finishing it (Vikunja #512). Same two moods as task_done_words and the same matching rule. Separate from the done words because the store records which of the two happened and /tasks shows it: dropped work he chose to stop is not work he did.",
|
||
"words": [
|
||
"убери", "уберите", "убрать", "удали", "удалить", "отмени", "отменить",
|
||
"drop", "remove", "cancel",
|
||
"передумал", "передумала", "неактуально"
|
||
]
|
||
}
|
||
}
|
||
}
|