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>
Every token of "что у меня сегодня?" is frame, so ownContent left nothing,
needsRoute returned false and no route was computed at all. The parked reminder
then read "сегодня" as its time and the question was answered nowhere.
A question shape now gets routed even when it leaves no content of its own, and
a role that fills nothing she asked about is decided by the route. A statement
he makes mid-flow gets a role of its own, roleAside, so a note or a fact is
stored and the question comes back instead of being dropped in silence.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
V-560 classified the side query correctly and then dropped the request behind
it, saying "Прошлую просьбу отпускаю." The owner rejected that on sight: he
asked about the weather in the middle of setting a reminder, and being told the
reminder was let go reports a loss he did not ask for. It had not been lost —
there was simply nowhere to put it.
There is now. ClarifyStore grew a bounded stack in V-559 and nothing called
Push; this is the caller it was built for. A side query leaves the question
parked exactly as it is, the words are answered as themselves, and the question
comes back on the end of the same reply — one utterance, two acts.
The resumed question is not the first one again. "Когда?" works in the same
breath as "напомни позвонить маме" and does not work after a turn about Rome, so
the deck has a second form per slot that names the request: "На какое время
поставить напоминание?". No attempt is spent, because he answered the side query
and not the parked question, and charging a retry for a turn that was never an
answer is the V-554 shape.
clarifyDropped stays for new_request and cancel, where something really does
die. Two things can now die at once, so TakeExpired reports a count instead of a
bool and the expiry notice has a plural wording — "прошлую просьбу" when two
were lost would be a lie about the number.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
turnRoute memoises this turn's routing, so the resolver that reads it to
classify a role and the pipeline that acts on it cannot end up with two
different decisions, and the extra route is paid once. needsRoute is the fast
path: an utterance with no content of its own reaches the same role without the
model.