question dismissal, A2: the silent write + the dismissal pause (owner design 2026-10-03)
- {type:"dismiss"} input event: parse + pure appends with the answer-event
orphan discipline (dangling-call 400, kind match, answer must be dismissed)
- POST /api/chats/[id]/dismiss: the no-turn composition — write-ahead append,
409 while a turn runs, emits record-changed (new bus word; idle views sync)
- needsContinuation: an all-dismissed trailing batch demands nothing;
endsInDismissal = the derived pause predicate (tail-based, no latch)
- wake pipeline: while the record ends in a dismissal the pump holds every
delivery in the steer queue — the user's next send is the wake (until the
text-turn steer claim lands, settlement re-pump delivers right after it)
- session-core.dismissQuestion: optimistic skipped card + silent POST;
chat.tsx confirmAbort question-mode swaps submitAnswer for it; ESC-abort
popup everywhere (AbortTurnDialog) with popup-Esc claimed via state gate
- parallel question calls dismiss call-by-call (results bind by id)
This commit is contained in:
+12
-1
@@ -64,7 +64,7 @@ import {
|
||||
type SteerMessage,
|
||||
} from "../core/contracts.ts";
|
||||
import type { TurnInput } from "../core/input-events.ts";
|
||||
import { danglingQuestionOf } from "../core/native-messages.ts";
|
||||
import { danglingQuestionOf, endsInDismissal } from "../core/native-messages.ts";
|
||||
import { fireJobAbort, isJobLive } from "../agent/subagents/aborts.ts";
|
||||
import { stores } from "./stores.ts";
|
||||
import { isTurnRunning } from "./turn-liveness.ts";
|
||||
@@ -457,6 +457,17 @@ async function pump(chatId: string): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
||||
// THE DISMISSAL PAUSE (owner design 2026-10-03, "A2"): the record
|
||||
// ends in a user dismissal — the session waits for the USER. Hold
|
||||
// every marker in the queue (no wake fires) and return; the user's
|
||||
// next send is the wake that carries them (the in-run vehicle below
|
||||
// hands them to that turn once the text-claim lands — until then,
|
||||
// settlement re-pumps and lands them right after it). The pause is
|
||||
// derived from the tail, so any user message un-holds by construction.
|
||||
if (endsInDismissal(fresh.messages)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// DEQUEUE-AT-FIRE (the Wave C lesson from the Wave B regression):
|
||||
// the carried markers leave the registry BEFORE the turn runs —
|
||||
// the wake run's OWN follow-up poll must never see its own cargo,
|
||||
|
||||
Reference in New Issue
Block a user