Strings family 4: act and smart-home replies into acts_ru_v1.json #112

Closed
claude wants to merge 2 commits from task/504-strings-family-4-act-and-smart-home-repl into task/503-strings-family-3-query-answers-and-gaps
Contributor

Closes Vikunja #504.

Opened during an unattended overnight run: the diff-budget block was off (task overnight). Read the diff, not only the tests.

Acceptance criteria and quality gate are in TASK.md on this branch.
Review the review, not the diff — leave comments and the agent will apply them via task start 504.

Closes Vikunja #504. Opened during an unattended overnight run: the diff-budget block was off (`task overnight`). Read the diff, not only the tests. Acceptance criteria and quality gate are in `TASK.md` on this branch. Review the review, not the diff — leave comments and the agent will apply them via `task start 504`.
claude added 2 commits 2026-08-03 23:38:17 +02:00
What she says when a capability ran, refused, or could not be reached. Around
forty literals across ecosystem_acts.go, actions_act.go and smarthome.go.

"It ran", "it was refused", "the ecosystem is down" and "I could not work out
what you meant" keep four entries. One variant set across them would let a
failure report itself as a success, which is the only failure mode this family
has.

The lines that report an act as done are fixed rather than varied. A success
report that rewords itself is harder to trust when he is listening for it, and
the confirmations are fixed for the same reason: they carry an instruction.

internal/smarthome/ha.go keeps its own "готово". It is a device driver, and
wiring the copy deck into one is the wrong dependency — the daemon relays that
word, it does not speak it.
Also fixes a flake this stack introduced: the feeds test matched "ничего
нового" as a substring, and query_ru_v1.json can answer with "в лентах тихо".
It asks the entry now, like the others.
kami reviewed 2026-08-04 12:41:16 +02:00
@@ -0,0 +1,114 @@
{
Owner

bugs first — two silent, two register.

json
"act_done":        { "fixed": true, "variants": ["готово."] },
"act_done_out":    { "variants": ["готово: {out}", "сделала: {out}"] },
"act_done_entity": { "fixed": true, "variants": ["готово: {name}."] },
"act_confirm":        { "fixed": true, "variants": ["выполнить «{name}»? да или нет."] },
"act_confirm_entity": { "fixed": true, "variants": ["выполнить «{name}» для {name_entity}? да или нет."] },
"act_which":       { "variants": ["какую команду для {name}: {items}?"] },
"act_fail":        { "variants": ["не получилось выполнить команду."] },
"act_fail_out":    { "variants": ["не получилось выполнить команду: {out}"] },
"act_fail_entity": { "variants": ["не получилось выполнить команду для {name}."] },
"act_server_down": { "variants": ["инструмент есть, но сервер не подключён."] },
"act_withdrawn":   { "fixed": true, "variants": ["сервер больше не отдаёт этот инструмент — сняла его с разрешённых, посмотри /tools."] },
"act_needs_args":  { "variants": ["тут нужны аргументы, из голоса не соберу. угадывать не буду."] },
"eco_denied":      { "variants": ["доступ отклонён, проверь токен."] },
"eco_down":        { "variants": ["не отвечает, попробуй ещё раз."] },
"eco_ambiguous":   { "variants": ["что именно: {items}?"] },
"eco_unknown_entity": { "variants": ["не знаю, что это.", "такого у меня нет."] },
"eco_no_nexus":    { "variants": ["не с чем связать — Nexus не настроен."] },
"eco_about_what":  { "variants": ["про что именно?"] },
"eco_recall":      { "variants": ["я помню: {items}"] },
"attention_none":  { "variants": ["ничего не требует внимания."] },
"attention_list":  { "variants": ["требует внимания: {items}"] },
"attention_fail":  { "variants": ["не могу сейчас узнать, что требует внимания."] },
"attention_none_entity": { "variants": ["по «{name}» ничего нет.", "по «{name}» пока пусто."] },
"attention_list_entity": { "variants": ["по «{name}»: {items}"] },
"attention_fail_entity": { "variants": ["не могу сейчас узнать, что требует внимания по «{name}»."] },
"changes_none":    { "variants": ["изменений нет."] },
"changes_list":    { "variants": ["изменения: {items}"] },
"changes_fail":    { "variants": ["не могу сейчас узнать об изменениях."] },
"home_unreachable":{ "variants": ["дом не отвечает.", "не достучалась до дома."] },
"home_empty":      { "variants": ["дом ничего не отдаёт."] },
"home_on":         { "variants": ["включено: {items}"] },
"home_dark":       { "variants": ["не отвечают: {count} {word}."] }

bug 1 — act_confirm_entity has an undeclared placeholder. it uses {entity}, your notes declare {name}, and {name} is already in the same string. either the Go side fills two different keys or that variant renders with a literal {entity} in it — in a confirmation prompt for a destructive action, which is the worst place for it. rename explicitly, whatever the caller actually passes.

bug 2 — «дом молчит» is in two entries that mean different things. home_empty (nothing returned) and home_dark ({count} devices unreachable) both open with it. your own note says four truths keep four entries so a failure can't report as a success — and then two of them share an opener. home_dark should lead with the count, since that's the only part he can act on.

{word} is also undeclared, and i assume it's your declension helper — устройство / устройства / устройств. that's the right fix (same trap as градусов in the query file), just document it, and make sure the same helper covers {count} anywhere else it lands.

register cuts, same two filters:

«сущность» has to go. «не знаю такой сущности.» is schema vocabulary spoken out loud — same disease as «записала факт.» and {fn}. she's talking about a lamp or a server, not an entity.
«экосистема» — flagging rather than deleting, since it might be your own name for the platform. but if it isn't the word you'd say to a person, it's the same leak. i dropped it where the sentence works without it.
«команда выполнена для {name}.» — passive-bureaucratic, and it's the one success line that didn't match «готово.» kept fixed, fixed the register.
«скажи «да» или «нет».» — phone-tree instruction. he knows how to answer a yes/no. trimmed to «да или нет.» — keep the longer form only if the voice parser genuinely needs the prompt spoken.
explanatory long-forms shortened (act_server_down, act_needs_args). «угадывать не буду» survives intact — that's the world_gap promise clause and it's the most important string in any of these files.
passive doubles and tomato pairs cut, consistent with the last two files.

one thing to check caller-side rather than here: act_which, attention_list, changes_list, home_on, eco_recall, eco_ambiguous are all single-variant and all placeholder-only. that's fine if the caller never emits them with an empty list — but that's exactly how net_empty went silent. worth one guard: empty {items} should route to the corresponding _none entry, not into the phraser.

bugs first — two silent, two register. ``` json "act_done": { "fixed": true, "variants": ["готово."] }, "act_done_out": { "variants": ["готово: {out}", "сделала: {out}"] }, "act_done_entity": { "fixed": true, "variants": ["готово: {name}."] }, "act_confirm": { "fixed": true, "variants": ["выполнить «{name}»? да или нет."] }, "act_confirm_entity": { "fixed": true, "variants": ["выполнить «{name}» для {name_entity}? да или нет."] }, "act_which": { "variants": ["какую команду для {name}: {items}?"] }, "act_fail": { "variants": ["не получилось выполнить команду."] }, "act_fail_out": { "variants": ["не получилось выполнить команду: {out}"] }, "act_fail_entity": { "variants": ["не получилось выполнить команду для {name}."] }, "act_server_down": { "variants": ["инструмент есть, но сервер не подключён."] }, "act_withdrawn": { "fixed": true, "variants": ["сервер больше не отдаёт этот инструмент — сняла его с разрешённых, посмотри /tools."] }, "act_needs_args": { "variants": ["тут нужны аргументы, из голоса не соберу. угадывать не буду."] }, "eco_denied": { "variants": ["доступ отклонён, проверь токен."] }, "eco_down": { "variants": ["не отвечает, попробуй ещё раз."] }, "eco_ambiguous": { "variants": ["что именно: {items}?"] }, "eco_unknown_entity": { "variants": ["не знаю, что это.", "такого у меня нет."] }, "eco_no_nexus": { "variants": ["не с чем связать — Nexus не настроен."] }, "eco_about_what": { "variants": ["про что именно?"] }, "eco_recall": { "variants": ["я помню: {items}"] }, "attention_none": { "variants": ["ничего не требует внимания."] }, "attention_list": { "variants": ["требует внимания: {items}"] }, "attention_fail": { "variants": ["не могу сейчас узнать, что требует внимания."] }, "attention_none_entity": { "variants": ["по «{name}» ничего нет.", "по «{name}» пока пусто."] }, "attention_list_entity": { "variants": ["по «{name}»: {items}"] }, "attention_fail_entity": { "variants": ["не могу сейчас узнать, что требует внимания по «{name}»."] }, "changes_none": { "variants": ["изменений нет."] }, "changes_list": { "variants": ["изменения: {items}"] }, "changes_fail": { "variants": ["не могу сейчас узнать об изменениях."] }, "home_unreachable":{ "variants": ["дом не отвечает.", "не достучалась до дома."] }, "home_empty": { "variants": ["дом ничего не отдаёт."] }, "home_on": { "variants": ["включено: {items}"] }, "home_dark": { "variants": ["не отвечают: {count} {word}."] } ``` bug 1 — act_confirm_entity has an undeclared placeholder. it uses {entity}, your notes declare {name}, and {name} is already in the same string. either the Go side fills two different keys or that variant renders with a literal {entity} in it — in a confirmation prompt for a destructive action, which is the worst place for it. rename explicitly, whatever the caller actually passes. bug 2 — «дом молчит» is in two entries that mean different things. home_empty (nothing returned) and home_dark ({count} devices unreachable) both open with it. your own note says four truths keep four entries so a failure can't report as a success — and then two of them share an opener. home_dark should lead with the count, since that's the only part he can act on. {word} is also undeclared, and i assume it's your declension helper — устройство / устройства / устройств. that's the right fix (same trap as градусов in the query file), just document it, and make sure the same helper covers {count} anywhere else it lands. register cuts, same two filters: «сущность» has to go. «не знаю такой сущности.» is schema vocabulary spoken out loud — same disease as «записала факт.» and {fn}. she's talking about a lamp or a server, not an entity. «экосистема» — flagging rather than deleting, since it might be your own name for the platform. but if it isn't the word you'd say to a person, it's the same leak. i dropped it where the sentence works without it. «команда выполнена для {name}.» — passive-bureaucratic, and it's the one success line that didn't match «готово.» kept fixed, fixed the register. «скажи «да» или «нет».» — phone-tree instruction. he knows how to answer a yes/no. trimmed to «да или нет.» — keep the longer form only if the voice parser genuinely needs the prompt spoken. explanatory long-forms shortened (act_server_down, act_needs_args). «угадывать не буду» survives intact — that's the world_gap promise clause and it's the most important string in any of these files. passive doubles and tomato pairs cut, consistent with the last two files. one thing to check caller-side rather than here: act_which, attention_list, changes_list, home_on, eco_recall, eco_ambiguous are all single-variant and all placeholder-only. that's fine if the caller never emits them with an empty list — but that's exactly how net_empty went silent. worth one guard: empty {items} should route to the corresponding _none entry, not into the phraser.
kami requested changes 2026-08-04 12:50:57 +02:00
kami left a comment
Owner

see comment for json.

see comment for json.
Author
Contributor

Landed transitively. This branch is already an ancestor of master, so there is nothing left to merge and Gitea did not close the pull request on its own.

Reviewed as part of a bottom-up pass over the open stack. The four open findings from that pass are worth a follow-up task, and none of them blocks anything here:

  • internal/router/stage0.go has two grammars named rest-of-day-query, and the second is dead.
  • internal/router/numwords.go holds ruNumerals, a second copy of the lexicon cardinals.
  • cmd/mavend/reminderbody.go and cmd/mavend/historyq.go still match Russian by hand.
  • internal/weather/openmeteo.go guesses declension by reversing endings, and bails under four runes.
Landed transitively. This branch is already an ancestor of `master`, so there is nothing left to merge and Gitea did not close the pull request on its own. Reviewed as part of a bottom-up pass over the open stack. The four open findings from that pass are worth a follow-up task, and none of them blocks anything here: - `internal/router/stage0.go` has two grammars named `rest-of-day-query`, and the second is dead. - `internal/router/numwords.go` holds `ruNumerals`, a second copy of the lexicon `cardinals`. - `cmd/mavend/reminderbody.go` and `cmd/mavend/historyq.go` still match Russian by hand. - `internal/weather/openmeteo.go` guesses declension by reversing endings, and bails under four runes.
claude closed this pull request 2026-08-04 18:35:04 +02:00

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: kami/Maven#112