fix(agent-loop): address second-round review — disposal discard, injection validation, frozen payloads

Address the review bot's five genuinely-new findings on the current code:
- disposal now discards any still-pending inbox items before the loop
  exits, so every enqueued id gets a terminal lifecycle event.
- injection (next-step/no-wakeup) validates its payload up front, before
  opening the idle one-shot turn, honoring 'invalid input throws before
  any append'; and rejects attached contexts (which belong only to inbox
  messages) rather than silently dropping them.
- agentMessage() freezes the agent/inbox/* payload so a listener cannot
  mutate the shared correlation object mid-dispatch.
- refresh the package READMEs (compact, goal, guard, hook-protocol,
  plan-mode, time-context, workspace-context) that still referenced the
  removed context/message event, with the source-based user/message
  distinction.

The up-front injection validation makes two finally branches unreachable
(v8-ignored as the turn-enclosure backstop). Adds regression tests for
disposal discard, context rejection, up-front validation, and the frozen
payload; per-file coverage stays 100%.
This commit is contained in:
Turtle
2026-07-24 12:05:57 +08:00
parent 7b7f793ee5
commit c7c1b97501
14 changed files with 127 additions and 62 deletions

View File

@@ -33,7 +33,7 @@ The private per-session cache is keyed by `session.surface.replaceGeneration` an
## Surface contract
`SurfaceEventType` is a closed union — only `user/message`, `assistant/message`, `tool/result`, `context/message`, and `steering/message` may carry `surfaceOp`. A `compact/*` event therefore **cannot** appear on the surface. A successful compaction instead:
`SurfaceEventType` is a closed union — only `user/message`, `assistant/message`, `tool/result`, and `steering/message` may carry `surfaceOp`. A `compact/*` event therefore **cannot** appear on the surface. A successful compaction instead:
1. appends `compact/start` (log-only) — acquires the lock,
2. summarizes the range,