Commit Graph

16 Commits

Author SHA1 Message Date
YeonGyu-Kim 0ad4d974f1 fix(background-agent): preserve parent activity across idle events
Cubic caught that clearing recent parent activity on session.idle could reopen the stale-idle race. Keep the fresh activity marker until its normal expiry so background completions still defer while the parent turn is actively reasoning.

Red: parent idle after fresh reasoning delta dispatched an unexpected parent wake. Green: focused parent-wake regression suite passes.
2026-05-21 12:07:40 +09:00
YeonGyu-Kim a8201726ef fix(background-agent): defer parent wakes during active turns
Record fresh parent session message activity before parent-wake flushing so stale idle status cannot dispatch a background completion into a live reasoning turn.

Add regression coverage for the Discord 4.2.3/OpenCode 1.15.5 duplicate-branch repro shape where a parent reasoning delta arrives before the background all-complete wake.

Refs #4212

Refs #4019

Refs #3774

Plan: plans/background-notification-active-turn-queue.md
2026-05-21 11:50:30 +09:00
YeonGyu-Kim 11d2cfb8a8 fix(background-agent): re-enqueue parent wake on same-source reservation instead of dropping
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-20 13:24:08 +09:00
YeonGyu-Kim d3e218f912 fix(prompt): treat post-dispatch failures as accepted 2026-05-20 11:42:32 +09:00
YeonGyu-Kim b2918fd4db fix(team-mode): close peer message delivery races 2026-05-19 19:18:13 +09:00
YeonGyu-Kim bcea4a9d28 fix(prompt-gate): harden sync and team prompt dispatch 2026-05-19 19:18:13 +09:00
YeonGyu-Kim 1492bffd20 fix(prompt-gate): harden internal prompt dispatch 2026-05-19 19:18:13 +09:00
YeonGyu-Kim 5f733f471c fix(parent-wake): recognize sdk tool progress 2026-05-19 13:48:26 +09:00
YeonGyu-Kim d3d2d4913b fix(parent-wake): preserve stale tool-call wake escape 2026-05-19 13:16:39 +09:00
YeonGyu-Kim b53a8b5e09 fix(parent-wake): close duplicate wake races 2026-05-19 13:16:39 +09:00
YeonGyu-Kim 33b66376d7 fix(background-agent): defer live tool-turn wakes
Require the latest assistant tool-wait turn itself to be stale before a shouldReply parent wake can bypass tool-call deferral. This prevents an all-complete background wake from forking a second parent prompt loop when OpenCode has repaired the tail to a synthetic user message.

Tests:

- bun test src/features/background-agent/parent-wake-user-message-race.test.ts src/features/background-agent/task-completion-cleanup.test.ts src/hooks/shared/prompt-async-gate.test.ts src/shared/prompt-async-route-audit.test.ts --bail

- bun run typecheck

- bun test
2026-05-19 10:06:25 +09:00
YeonGyu-Kim af1ad4d04b fix(background-agent): coalesce parent wake races
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 15:38:52 +09:00
Claude Agent 3294128271 fix(background-agent): defer parent-wake when a user message just arrived (fixes #4120)
When a background subagent emits [ALL BACKGROUND TASKS COMPLETE], the
plugin queues a parent-wake that ultimately calls
dispatchInternalPrompt against the parent session. If the user submits
a new prompt inside the ~250 ms post-dispatch hold window, both writes
land on the same OpenCode session-storage file at the same instant.
OpenCode's @parcel/watcher (which the plugin itself does not depend on,
but does indirectly trigger) batches those events into a TSFN callback
and dispatches them into a JS env that the renderer has just torn down
because the session view re-mounted around the user's new message ->
napi_fatal_error / SIGABRT on macOS arm64. Removing the plugin removes
the parent-wake, which is why removing OmO eliminates the crash.

Mitigation:
- Before flushPendingParentWake calls dispatchInternalPrompt, inspect
  the parent session's message tail. If the most recent message is a
  user message added inside PARENT_WAKE_USER_MESSAGE_IN_PROGRESS_WINDOW_MS
  (default 2_000 ms), reschedule instead of dispatching. The user's own
  prompt will drive the model; queued notifications will be re-flushed
  on the next idle.
- Best-effort unref() of the long-lived pending-retry and dispatched-
  wake bookkeeping setTimeouts. They previously pinned the host event
  loop and prolonged the teardown window during which the watcher race
  can fire.

The new option userMessageInProgressWindowMs is wired through
BackgroundManager via a module-level constant and is independently
testable.

Regression test parent-wake-user-message-race.test.ts covers:
- fresh user message -> dispatch deferred
- latest message is assistant -> dispatch proceeds
- user message older than window -> dispatch proceeds
- window=0 disables the guard

This is a surface-level mitigation of the most-likely root cause from
the audit; a deeper fix (singleton guard against plugin
double-instantiation under @opencode-ai/plugin@local reload, dispose
lifecycle for OpenCode plugin reload) is out of scope here.
2026-05-17 21:27:11 +02:00
YeonGyu-Kim df198d8b2d refactor(background-agent): use unified internal prompt dispatch
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-17 16:44:56 +09:00
YeonGyu-Kim f43effb842 fix(session-recovery): recover interrupted idle tool turns 2026-05-17 15:08:39 +09:00
YeonGyu-Kim c1ccf8d096 refactor(background-agent): introduce ParentWakeNotifier module
Extracts the parent-wake coalescing logic (pending/dispatched wake maps,
timers, notification reply assembly) from manager.ts into a standalone
ParentWakeNotifier class. Takes dependency-injected client, directory,
and an enqueueNotificationForParent callback, so the manager can delegate
parent-wake state to a narrow API.

This commit only introduces the new module; wiring manager.ts to use it
is a follow-up commit so the refactor stays atomic (HIGH-9 step 1 of 2).

Closes HIGH-9 (step 1: extraction)
Refs HIGH-9 (step 2: manager.ts integration deferred until verification)

Co-authored-by: manager-extract (deep / gpt-5.3-codex high)
2026-05-16 00:49:50 +09:00