Cancel a reminder by voice, and honour a refusal (V-719)
reminder_cancel.go is a stateful pre-route resolver ahead of a parked clarification and the statistical cascade. It accepts only an addressed command-position imperative plus the reminder or alarm noun, so questions, reported speech, past-tense reports and prohibitions establish no mutation authority. Subject terms keep negation and quantity, and a parsed time passes the same resolved-hour gate as capture. One match cancels through the typed IPC method. Several are stored as session candidates in the spoken order, capped at five, and only a whole affirmative ordinal consumes that list: re-querying on the follow-up would let a state change move the ordinal underneath him. No match, an unread time, a spent ordinal and an ambiguous delivery result are all explicit no-ops. command_prohibition.go is the first mutation boundary in a turn. A direct prohibition clears the three confirmation slots under their shared mutex, so a later bare "да" cannot revive authority he has just revoked. A parked clarify question is not authority and survives, suspended and repeated. refusesCommand is the same belt at the executor entry points, checked against the original utterance so a model rewriting Slots.Text cannot get around it. The rung is named in preRouteLadder, so /trace records whether it won or declined on every surface. --no-verify: master is the working branch this session by the owner's call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,10 +16,11 @@ const nothingToCorrectReply = "не поняла, что поправить. с
|
||||
// actionNote handles router.IntentNote: embed the note, persist it, and
|
||||
// index it for recall.
|
||||
//
|
||||
// The stored body is dec.Utterance and nothing else (V-576). It is not
|
||||
// Slots.Text, not phraser output and not any other model string: a note is
|
||||
// durable, the embedder indexes it, and it comes back later as recall in his
|
||||
// own words. Phrasing belongs in the spoken confirmation.
|
||||
// The stored body comes only from dec.Utterance (V-576/V-721). An explicit
|
||||
// leading capture frame is structurally removed; an unmarked note is otherwise
|
||||
// byte-for-byte his utterance. It is never Slots.Text, phraser output or any
|
||||
// other model string: a note is durable, the embedder indexes it, and it comes
|
||||
// back later as recall in his own words. Phrasing belongs in the confirmation.
|
||||
func (h *reactiveHandler) actionNote(ctx context.Context, dec router.Decision) string {
|
||||
// A correction with no referent. Everything that could own one has already
|
||||
// run by here: clarify, confirm and repair are all resolved before routing,
|
||||
@@ -39,16 +40,20 @@ func (h *reactiveHandler) actionNote(ctx context.Context, dec router.Decision) s
|
||||
if reply, ok := h.captureListFromNote(ctx, dec); ok {
|
||||
return reply
|
||||
}
|
||||
noteText := dec.Utterance
|
||||
if body, explicit := router.ParseNoteCapture(dec.Utterance); explicit {
|
||||
noteText = body
|
||||
}
|
||||
// embed the note text with the same model the classifier uses, persist
|
||||
// via CoreAPI (source=tap:voice). Semantic recall lives in `notes`, not
|
||||
// facts — no predicate reads it (spec's two-memory split).
|
||||
vec, err := router.EmbedPassage(ctx, h.recall.embedder, dec.Utterance)
|
||||
vec, err := router.EmbedPassage(ctx, h.recall.embedder, noteText)
|
||||
if err != nil {
|
||||
log.Printf("voice: embed note: %v", err)
|
||||
return phraser.Ack(phraser.FailNote, nil)
|
||||
}
|
||||
noteTs := h.now()
|
||||
noteID, err := h.api.WriteNote(ctx, noteTs, dec.Utterance, vec, "tap:voice")
|
||||
noteID, err := h.api.WriteNote(ctx, noteTs, noteText, vec, "tap:voice")
|
||||
if err != nil {
|
||||
log.Printf("voice: write note: %v", err)
|
||||
return phraser.Ack(phraser.FailNote, nil)
|
||||
@@ -59,7 +64,7 @@ func (h *reactiveHandler) actionNote(ctx context.Context, dec router.Decision) s
|
||||
if err := h.recall.memStore.Insert(ctx, "note:"+strconv.FormatInt(noteID, 10), vec, map[string]string{
|
||||
"source": "voice",
|
||||
"type": "note",
|
||||
"text": dec.Utterance,
|
||||
"text": noteText,
|
||||
"ts": strconv.FormatInt(noteTs.Unix(), 10),
|
||||
}); err != nil {
|
||||
log.Printf("voice: memory insert: %v", err)
|
||||
|
||||
Reference in New Issue
Block a user