reminders: store what she says, show it in his clock (V-469)

Two of the four defects on the task.

The stored payload was the whole utterance, so /reminders and the agenda
recited "напомни завтра в 9 утра выпить таблетки" where the reminder is
"выпить таблетки". The marker is an instruction that was already carried out
and the hour is already a column, so reminderBody strips both, and falls back
to the unstripped body whenever stripping would leave nothing — a reminder
that fires and says nothing is worse than a wordy one.

The page rendered the raw {"text":...} envelope and the UTC instant. Both are
now done in mavweb: reminderRows unwraps the payload and formats through
Local(). The unwrap is a copy of store.ReminderText rather than a call to it,
because mavweb builds without CGO and internal/store carries the sqlite
driver — the ipc DTOs are decoupled from the store on purpose.

TestClarifySubjectAnswerFillsRatherThanClobbers asserted the hour survived as
a word in the payload. It now asserts the fire time, which is where the hour
lives.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-04 03:53:20 +04:00
parent 442d3ec08e
commit df58710141
7 changed files with 179 additions and 7 deletions
+4 -1
View File
@@ -24,7 +24,10 @@ func (h *reactiveHandler) actionReminder(ctx context.Context, dec router.Decisio
return "не получилось разобрать время напоминания."
}
}
payload := `{"text":` + jsonString(dec.Utterance) + `}`
// The body is what she says at the hour, so the marker and the time come
// out of it: the fire time is already a column, and "напомни" is an
// instruction that has been carried out (Vikunja #469).
payload := `{"text":` + jsonString(reminderBody(dec.Utterance, dec.Slots.Text)) + `}`
if _, err := h.api.CreateReminder(ctx, dec.Slots.Time, payload, ""); err != nil {
log.Printf("voice: create reminder: %v", err)
return "не получилось поставить напоминание."