06ddf41228
nudgeValues filled {service} from State.Fact("service_down"), an exact key
mavpoll stopped writing when per-monitor facts landed. The lookup could never
hit, so every variant carrying {service} was rejected as unfillable and the one
nameless variant was the only usable template, every time. A sev4 reaching him
on telegram said only that a service was down.
It now reads loop.DownServices, the same helper the rule fires on, so the
message cannot name a service that is up. Dropped the nameless variant and the
{since} one: service_down facts are keyed by monitor and the rule is
edge-triggered, so neither can fill. service_down joins routine and morning as
a family that always carries a name.
The tests passed through all of this because cand() built the pre-per-monitor
aggregate shape. downCand() builds what a tick actually produces.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011x5DgnExQ5XZy8TZPs5bot
128 lines
6.2 KiB
JSON
128 lines
6.2 KiB
JSON
{
|
||
"schema_version": 1,
|
||
"name": "russian nudge templates v1",
|
||
"notes": [
|
||
"Hand-written Russian nudges. Edit the wording here, no Go changes needed.",
|
||
"Rules: she is feminine about herself, he is a man addressed as ты. Never вы/вас/ваш, never plural imperatives (выпейте), never он/его about him.",
|
||
"One short sentence. No questions, no emoji, no pet names, no emotional support.",
|
||
"Placeholders: {since} how long it has been (only used when it is at least an hour), {service} the service name, {what} the routine name. A variant whose placeholder has no value is skipped, so every rule needs at least one variant with no placeholder. The exception is routine and morning: those only exist for rules like routine:таблетки that always carry a name, and a routine nudge that drops the name is useless.",
|
||
"mood must be one of: neutral, happy, thinking, tired, confused."
|
||
],
|
||
"rules": {
|
||
"water": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"Ты не пил воду {since} — выпей стакан.",
|
||
"Пора выпить воды.",
|
||
"Стакан воды не помешает.",
|
||
"Воду ты не пил уже {since}.",
|
||
"Напоминаю про воду.",
|
||
"Сходи за водой, дела подождут.",
|
||
"Сделай глоток воды, пока помнишь.",
|
||
"Между делом выпей воды.",
|
||
"Вода — простое дело: выпей стакан.",
|
||
"Отвлекись на стакан воды."
|
||
]
|
||
},
|
||
"meal": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"Ты не ел {since} — поешь.",
|
||
"Пора поесть, сделай перекус.",
|
||
"Еда важнее ещё одного часа за столом.",
|
||
"Без еды уже {since}, поешь.",
|
||
"Напоминаю про еду — поешь.",
|
||
"Возьми перерыв на обед.",
|
||
"Сделай себе перекус, это пять минут.",
|
||
"Поешь, потом вернёшься к работе.",
|
||
"Поешь нормально, а не на ходу.",
|
||
"Еды не было {since} — разогрей что-нибудь."
|
||
]
|
||
},
|
||
"break": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"Ты за столом {since} — встань и разомнись.",
|
||
"Пора сделать перерыв.",
|
||
"Встань на пять минут.",
|
||
"{since} без перерыва — отойди от экрана.",
|
||
"Напоминаю про перерыв.",
|
||
"Разомни спину, потом продолжишь.",
|
||
"Короткая пауза не сорвёт дела.",
|
||
"Отойди от компьютера на минуту.",
|
||
"Сидишь без перерыва {since}.",
|
||
"Встань, пройдись, вернись."
|
||
]
|
||
},
|
||
"service_down": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"Сервис {service} не отвечает.",
|
||
"{service} упал — сервис не отвечает.",
|
||
"{service} не отвечает, сервис нужно поднимать.",
|
||
"Сервис {service} недоступен.",
|
||
"Проверь {service}: сервис не отвечает.",
|
||
"Сервис {service} лежит, нужно смотреть.",
|
||
"Мониторинг сообщает: {service} лежит.",
|
||
"Сервис {service} не отвечает, посмотри логи."
|
||
]
|
||
},
|
||
"netdata_critical": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"Netdata: критический алярм, проверь диск.",
|
||
"Критический алярм в netdata — посмотри диск.",
|
||
"Netdata поднял тревогу по диску.",
|
||
"Проверь диск: netdata ругается.",
|
||
"Алярм от netdata, критический.",
|
||
"Netdata: критический уровень, дело в диске.",
|
||
"Диск требует внимания — критический алярм в netdata.",
|
||
"Критический алярм: проверь место на диске.",
|
||
"Netdata сообщает о критической проблеме с диском.",
|
||
"Открой netdata: там критический алярм по диску."
|
||
]
|
||
},
|
||
"routine": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"По распорядку: {what}.",
|
||
"Пора — {what}.",
|
||
"Напоминаю: {what}.",
|
||
"В списке на сейчас: {what}.",
|
||
"{what} — сейчас самое время.",
|
||
"Не пропусти: {what}.",
|
||
"{what}: пора сделать.",
|
||
"Сейчас по плану {what}.",
|
||
"Твой распорядок: {what}.",
|
||
"{what} — по распорядку сейчас."
|
||
]
|
||
},
|
||
"morning": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"{what} — пора начать день.",
|
||
"{what}: пройди утренний список.",
|
||
"Начни {what} со списка.",
|
||
"{what}. Осталось пройти чеклист.",
|
||
"Утренний список ещё не пройден: {what}.",
|
||
"{what}: первый пункт списка за тобой.",
|
||
"{what} идёт, а список стоит.",
|
||
"{what}: не забудь про утренние дела.",
|
||
"По утреннему чеклисту ещё есть дела: {what}.",
|
||
"{what} — утренний список дел ещё ждёт."
|
||
]
|
||
},
|
||
"default": {
|
||
"mood": "neutral",
|
||
"variants": [
|
||
"Напоминаю: есть дело.",
|
||
"Пора вернуться к отложенному делу.",
|
||
"Одно дело ждёт тебя.",
|
||
"Напоминаю про дело из списка.",
|
||
"В списке осталось дело.",
|
||
"Дело всё ещё не сделано."
|
||
]
|
||
}
|
||
}
|
||
}
|