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:
2026-08-15 17:19:25 +04:00
parent 0b057df2a3
commit 85a3397bf4
26 changed files with 1746 additions and 37 deletions
+12 -1
View File
@@ -658,6 +658,12 @@ func (h *reactiveHandler) resolveEntityCandidates(ctx context.Context, refs []st
// matching capabilities through Hexis. Returns a reply string when handled,
// or "" to fall through to the system command executor.
func (h *reactiveHandler) handleHexisAct(ctx context.Context, dec router.Decision) string {
// This method is intentionally callable outside runTurn by ecosystem
// harnesses. Refuse before correlation ids, Nexus resolution or capability
// discovery so the no-op sentinel can never leak into Hexis as a verb.
if refusesCommand(dec) {
return commandProhibitionReply
}
if h.ecosystem == nil {
return ""
}
@@ -841,10 +847,15 @@ func (h *reactiveHandler) execHexis(ctx context.Context, capID, capName, entityI
// resolution stops on ambiguity and a mutating capability still goes through
// the spoken confirm in handleHexisAct.
func (h *reactiveHandler) hexisBeforeClarify(ctx context.Context, dec router.Decision) string {
// A thinned model act reaches this hook before actionAct. Negative authority
// must therefore stop here as well, before even a read to Nexus/Hexis.
if refusesCommand(dec) {
return commandProhibitionReply
}
if h.ecosystem == nil || h.ecosystem.hexis == nil {
return ""
}
if dec.Intent != router.IntentAct || dec.Slots.HasFn || dec.Slots.Text == "" {
if dec.Intent != router.IntentAct || dec.Slots.HasFn || !router.ActHasEntityTarget(dec) {
return ""
}
return h.handleHexisAct(ctx, dec)