The real agent_end event always carries messages: AgentMessage[], but
this fixture used a bare { type: "agent_end" }. That was harmless
while sendCompletionNotification() ignored its event argument, but the
prior commit made it read event.messages, so this fixture now crashes
#finishAgentEnd with a TypeError. Add the missing field.
sendErrorNotification now reads the settled turn from event.messages,
but sendCompletionNotification still read viewSession.getLastAssistantMessage().
For a classifier-refusal turn that stale/undefined lookup no longer
matched 'aborted'/'error', so with completion.notify=on the same
failed turn fired both the error toast and a misleading 'Complete'
toast.
Thread the same agent_end event into sendCompletionNotification so
both gates read one consistent source of truth.
This branch tracked main forward through many merge commits over its
long life; four files carried stale fixups for intermediate states of
main that current main never needed (a test-title rename, retimed
pi-native stream fixtures, a mermaid-cache type refactor, and a
multi-path test rewrite). None relate to error.notify, and current
upstream/main's own versions of these files already pass. Restore them
to keep this PR scoped to the error-notification feature.
The entry landed inside the already-released ## [16.3.0] section as a
second ### Added heading, which released sections never carry (they
are immutable) and would be skipped by the normal release flow.
Classifier-refusal failures end a turn with stopReason === "error" but
get pruned from the active context (agent-session.ts's
#removeAssistantMessageFromActiveContext) before agent_end fires.
sendErrorNotification() read viewSession.getLastAssistantMessage(),
which reflects that mutated context and silently missed the
notification for exactly the turns it should fire on.
Thread the agent_end event through #handleAgentEnd -> #finishAgentEnd
so sendErrorNotification reads the turn's own outcome from
agent_end.messages instead.
- Upgraded puppeteer-core to version 25.3.0 to resolve stealth patch deactivation.
- Enabled main world execution support via the `!world=main` directive for frames and element handles.
- Improved handle management by updating disposal logic to track and clear main world handles.
- Optimized web worker communication by removing redundant Runtime.enable calls.
claude-sonnet-4-5's bundled context window grew to 1M in the catalog regen, so the fixed 191k high-usage turn no longer crossed the ~85% auto-compaction threshold. The auto-continuation never fired and the three re-injection tests hung to their 5s timeout, failing the coding-agent runtime/session CI bucket and blocking the release.
Pin the harness model to a 200k window (mirrors agent-session-eager-compaction / -auto-compaction-queue), keeping the trigger stable across future catalog regenerations.
- Updated event controller fixture to include requestComponentRender mock.
- Added test case for resolving deferred role-alias model patterns.
- Added test case for parsing and falling back comma-delimited model patterns.
- Implemented a 2-second timeout for `workspace/didChangeWatchedFiles` notifications to prevent agent stalls during server congestion.
- Updated `runLspWritethrough` to gracefully reset notification state when the internal watchdog triggers but the primary operation remains active.
- Added explicit abort signal checks in `acp-bridge` to prevent initiation of file writes after tool cancellation.
- Refactored `notifyWorkspaceWatchedFiles` to use `AbortSignal.any` for unified signaling across timeout and caller-provided triggers.
- Enabled comma-separated string splitting within array-based model patterns.
- Expanded deferred model patterns before registration to align with immediate resolution behavior.
- Unified resolution logic to ensure deferred patterns support the same role aliases and chaining as the standard path.
- Extracted gunzipRustdocJson() with overridable maxOutputLength so the cap contract is testable with real gzip payloads instead of the banned mock.module().