a side query suspends the flow instead of ending it (V-561)
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>
This commit is contained in:
@@ -207,23 +207,26 @@ func (s *ClarifyStore) Depth(id string) int {
|
||||
return len(s.stacks[id])
|
||||
}
|
||||
|
||||
// TakeExpired reports whether a question was parked here but its TTL ran out,
|
||||
// and drops it. Get drops such a question silently, which leaves the user
|
||||
// thinking his request is still alive — the caller uses this to tell him it is
|
||||
// gone before treating his words as a fresh utterance.
|
||||
// TakeExpired reports HOW MANY parked questions were dropped because the TTL
|
||||
// ran out, and drops them. 0 ⇒ nothing was parked, or what was parked is still
|
||||
// live. Get drops such a question silently, which leaves the user thinking his
|
||||
// request is still alive — the caller uses this to tell him it is gone before
|
||||
// treating his words as a fresh utterance.
|
||||
//
|
||||
// It looks at the top only, and drops the whole stack when that one is dead: one
|
||||
// notice is what a reply can carry, and anything parked under a question that
|
||||
// timed out has been waiting at least as long.
|
||||
func (s *ClarifyStore) TakeExpired(id string, now time.Time) bool {
|
||||
// It looks at the top only, and drops the whole stack when that one is dead:
|
||||
// anything parked under a question that timed out has been waiting at least as
|
||||
// long. The COUNT rather than a bool since V-561, because the stack can now
|
||||
// hold two — the flow and the side query that suspended it — and a notice
|
||||
// saying "прошлую просьбу" when two died is a lie about the count.
|
||||
func (s *ClarifyStore) TakeExpired(id string, now time.Time) int {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
stack := s.stacks[id]
|
||||
if len(stack) == 0 || !stack[len(stack)-1].IsExpired(now) {
|
||||
return false
|
||||
return 0
|
||||
}
|
||||
delete(s.stacks, id)
|
||||
return true
|
||||
return len(stack)
|
||||
}
|
||||
|
||||
// Delete drops every question parked for this id. The old single-slot Delete
|
||||
|
||||
Reference in New Issue
Block a user