Write the nudges from templates instead of asking the model (#392) #45

Closed
claude wants to merge 2 commits from overnight/nudge-templates into overnight/fix-truncation
Contributor

Nudges are the one path where Maven has nothing to figure out. The rule already
decided what to say; the model was only being asked to word it. It kept getting
that wrong — English, formal вы, masculine self-reference, questions.

So it no longer asks. 76 hand-written Russian lines in
internal/phraser/nudges_ru_v1.json, 10 per rule, picked by seed.

15 of 15 on the nudge fixture, every check, and it holds on all 60 seeds
swept.
Runs in about 70 ms with no model at all. The LLM path scored 21-22 of
27 on address and 24-26 on feminine no matter how the prompt was worded.

Time values are spelled out in words — "полтора часа", not "1.5 ч" — because
this goes to a piper voice. A variant whose value is missing is skipped, so a raw
{since} can never be spoken.

Deprecation, flagged: the model no longer writes nudges by default.
phraser.llm_nudges: true in deploy/mavend.json puts it back. Chat, query and
reminder phrasing are untouched and still go through the model — this is only the
path where the wording was never the interesting part.

Noticed and left alone: phraser.Stub still writes English nudges, and it is
what runs when phraser is absent from the config. Separate decision, since
TestStubBaseline deliberately documents the Stub as the English floor.

Two commits: the templates, then the wiring.

Vikunja #392.

Nudges are the one path where Maven has nothing to figure out. The rule already decided what to say; the model was only being asked to word it. It kept getting that wrong — English, formal вы, masculine self-reference, questions. So it no longer asks. 76 hand-written Russian lines in `internal/phraser/nudges_ru_v1.json`, 10 per rule, picked by seed. **15 of 15 on the nudge fixture, every check, and it holds on all 60 seeds swept.** Runs in about 70 ms with no model at all. The LLM path scored 21-22 of 27 on address and 24-26 on feminine no matter how the prompt was worded. Time values are spelled out in words — "полтора часа", not "1.5 ч" — because this goes to a piper voice. A variant whose value is missing is skipped, so a raw `{since}` can never be spoken. **Deprecation, flagged:** the model no longer writes nudges by default. `phraser.llm_nudges: true` in `deploy/mavend.json` puts it back. Chat, query and reminder phrasing are untouched and still go through the model — this is only the path where the wording was never the interesting part. Noticed and left alone: `phraser.Stub` still writes English nudges, and it is what runs when `phraser` is absent from the config. Separate decision, since `TestStubBaseline` deliberately documents the Stub as the English floor. Two commits: the templates, then the wiring. Vikunja #392.
kami changed target branch from overnight/eval-writeup to overnight/fix-truncation 2026-07-31 19:15:21 +02:00
kami added 2 commits 2026-07-31 19:15:21 +02:00
Nudge wording as data instead of generation. The wording lives in
internal/phraser/nudges_ru_v1.json (embedded), about 10 variants per rule:
water, meal, break, service_down, netdata_critical, routine:, morning:, plus
a contentless default. That JSON is long because it is data — the owner can
edit any line of Russian without touching Go.

The picker:
- random, but never the same variant twice in a row for the same rule
- deterministic when seeded (math/rand with an injectable source)
- fills {since} / {service} / {what} from the candidate, and skips any variant
  whose value is missing, so no raw placeholder can reach the piper voice
- {since} is spelled out in words ("полтора часа", "семь часов"), because
  "3 ч" is wrong in a Russian voice

Scores 15/15 on the existing nudge fixture, on every seed swept. Nothing is
wired yet — that is the next commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGeSZxh1DCtRxmFVSYVGvJ
DEPRECATION, flagged not asked: LLM-phrased nudges are no longer the default.
LLMPhraser.PhraseNudge now returns a hand-written Russian template. The model
still phrases chat, queries and reminders — only nudges moved.

Why: measured over many runs, Qwen3.5-0.8B wrote formal "вы" and plural
imperatives, used masculine self-reference, and invented facts and units
(90-95 seconds to boil an egg). A nudge is five words of known content, so
generation buys nothing and risks the persona every time. Templates score
15/15 on the nudge fixture, the model 11-13/15.

Nothing is deleted: the prompt, the fallbacks and the whole LLM nudge path
stay. Set phraser.llm_nudges = true in deploy/mavend.json to get them back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CGeSZxh1DCtRxmFVSYVGvJ
Owner

Superseded by #47, which landed this whole stack on master as one reviewed integration merge. This PR head is an ancestor of master — its commits are in, nothing here is lost. Closing as merged-by-proxy rather than merged, since the merge came in through #47.

Review threads on this PR were answered or acted on before the merge; the Russian wording fixes went in as #48.

Superseded by #47, which landed this whole stack on master as one reviewed integration merge. This PR head is an ancestor of master — its commits are in, nothing here is lost. Closing as merged-by-proxy rather than merged, since the merge came in through #47. Review threads on this PR were answered or acted on before the merge; the Russian wording fixes went in as #48.
kami closed this pull request 2026-07-31 20:22:46 +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#45