fix(loop): record a durable prompt/blocked for every vetoed prompt

Address review on the interception-seams PR: PromptDecision.reason is
documented as the durable record of why a prompt was blocked, but the loop
only surfaced it via the fully-blocked batch's `rejected` turn/end. In a MIXED
batch — one queued prompt blocked, another allowed — the turn does not end
`rejected`, so the blocked prompt and its reason vanished from the session log
entirely.

Add a `prompt/blocked` SessionEventMap variant (content + source + reason),
appended in the open turn at the veto point in place of the user/message the
prompt would have become. It is a non-surface, turn-enclosed event (like
todo/write): it never reaches deriveMessages(). The fully-blocked batch still
also ends `rejected` for boundary balance + ACP settlement. Regression test
drives a mixed batch and asserts the blocked prompt is recorded while the
allowed one runs — proven red without the append.
This commit is contained in:
Tianyi Cui
2026-07-02 17:03:53 +08:00
parent d3be934a17
commit abe80cec68
10 changed files with 101 additions and 22 deletions

View File

@@ -25,7 +25,7 @@ An agent was registered in the AgentRegistry and is ready to receive messages.
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:229`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:233`](../../packages/core/agent/src/types.ts)
#### `agent/disposed` — emit
@@ -37,7 +37,7 @@ An agent was disposed and removed from the registry; its fiber and any in-flight
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:235`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:239`](../../packages/core/agent/src/types.ts)
#### `agent/error` — emit
@@ -49,7 +49,7 @@ A step or turn errored. The loop reports a failure here (plus the logger) even w
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:354`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:358`](../../packages/core/agent/src/types.ts)
#### `agent/pre-step` — serial
@@ -63,7 +63,7 @@ Serial (awaited in registration order), not a waterfall: a listener mutates the
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:301`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:305`](../../packages/core/agent/src/types.ts)
#### `agent/prompt-submit` — waterfall
@@ -75,7 +75,7 @@ Waterfall: decide what happens to ONE drained queued message before it becomes a
Types: [Agent](../core-data-structures/core.md) · [ContentBlock](../core-data-structures/core.md) · [MessageSource](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:311`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:315`](../../packages/core/agent/src/types.ts)
#### `agent/queued` — emit
@@ -87,7 +87,7 @@ A message entered the agent's inbox (queued or steering). `source` is the resolv
Types: [Agent](../core-data-structures/core.md) · [ContentBlock](../core-data-structures/core.md) · [MessageSource](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:248`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:252`](../../packages/core/agent/src/types.ts)
#### `agent/request` — waterfall
@@ -99,7 +99,7 @@ Waterfall: mutate the fully-assembled GenerateOptions before the model call (hoo
Types: [Agent](../core-data-structures/core.md) · [GenerateOptions](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:320`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:324`](../../packages/core/agent/src/types.ts)
#### `agent/session-start` — emit
@@ -111,7 +111,7 @@ The agent's session lifecycle began, fired once before its first turn. `source`
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:261`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:265`](../../packages/core/agent/src/types.ts)
#### `agent/status` — emit
@@ -123,7 +123,7 @@ Agent status changed (`idle` ⇄ `running`, or → `disposed`). Drive lifecycle
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:242`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:246`](../../packages/core/agent/src/types.ts)
#### `agent/steering` — emit
@@ -135,7 +135,7 @@ Steering content was injected into a running turn.
Types: [Agent](../core-data-structures/core.md) · [ContentBlock](../core-data-structures/core.md) · [MessageSource](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:348`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:352`](../../packages/core/agent/src/types.ts)
#### `agent/step-result` — waterfall
@@ -147,7 +147,7 @@ Waterfall: post-process the assembled assistant Message before tool dispatch (va
Types: [Agent](../core-data-structures/core.md) · [Message](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:326`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:330`](../../packages/core/agent/src/types.ts)
#### `agent/stream-chunk` — emit
@@ -159,7 +159,7 @@ A raw StreamChunk arrived from the model (token-level UI/log feed).
Types: [Agent](../core-data-structures/core.md) · [StreamChunk](../core-data-structures/llm-streaming.md)
Source: [`packages/core/agent/src/types.ts:343`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:347`](../../packages/core/agent/src/types.ts)
#### `agent/turn-continuation` — waterfall
@@ -171,7 +171,7 @@ Waterfall: override the turn-continuation decision via a typed ContinuationDecis
Types: [Agent](../core-data-structures/core.md)
Source: [`packages/core/agent/src/types.ts:336`](../../packages/core/agent/src/types.ts)
Source: [`packages/core/agent/src/types.ts:340`](../../packages/core/agent/src/types.ts)
### `llm/*`