Summary:
- The PR changes generated-media duplicate guards, completion delivery fallback behavior, transcript write-lock reuse, task-registry fresh owner reads, docs, changelog, and regression coverage.
- Reproducibility: yes. with source and artifact evidence rather than a local rerun: current main completes me ... e task and one successful video task after the patch. I did not run tests because this review is read-only.
Automerge notes:
- PR branch already contained follow-up commit before automerge: fix: dedupe media completion delivery
- PR branch already contained follow-up commit before automerge: fix: avoid music provider lookup for explicit models
- PR branch already contained follow-up commit before automerge: fix: narrow detached media task handles
- PR branch already contained follow-up commit before automerge: fix: close media completion review gaps
- PR branch already contained follow-up commit before automerge: fix: tolerate media delivery mirrors during session lock
- PR branch already contained follow-up commit before automerge: Fix media completion duplicate delivery
Validation:
- ClawSweeper review passed for head f83e3bf143.
- Required merge gates passed before the squash merge.
Prepared head SHA: f83e3bf143
Review: https://github.com/openclaw/openclaw/pull/84006#issuecomment-4484835103
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
Raise bounded gateway lifecycle hook wait budgets to 5 seconds for shutdown and 10 seconds for pre-restart, keeping the fix to defaults only instead of adding config surface.
Includes regression coverage, hook docs, changelog credit for @bryanbaer, and replaces #82186 with the narrower maintainer fix.
* fix(heartbeat): unblock beads cadence — parallel broadcast, agent-scoped busy check, full HEARTBEAT.md prompt, connect-timeout, doctor warning
* docs(changelog): note heartbeat cadence fixes
* fix(heartbeat): address review feedback
* fix(heartbeat): append HEARTBEAT.md directives to commitment-only task dispatch (review feedback)
* docs(changelog): extend heartbeat fix entry — commitment-only task dispatch path (review feedback)
* fix(heartbeat): clear connect timer on synchronous baseFn throw (review feedback)
When the provider stream function passed to streamWithIdleTimeout throws
synchronously during setup, the connect watchdog timer was left armed
and could fire onIdleTimeout later with a stale error, keeping the
process open past the real failure. Wrap the synchronous baseFn(...)
invocation in a try/catch that clears the connect timer before
rethrowing, and add a regression test that asserts onIdleTimeout is
not invoked after the synchronous throw.
* docs(changelog): note round-4 heartbeat fix (review feedback)
Bump the heartbeat fixes list from six to seven and document the
synchronous-baseFn-throw connect-timer cleanup added in the prior
commit.
* fix(heartbeat): honor omitted doctor target (review feedback)
* fix(heartbeat): merge doctor heartbeat defaults (review feedback)
Teach the heartbeat session-target doctor warning to enumerate the same agents as the runtime heartbeat runner and merge agents.defaults.heartbeat with per-agent overrides before checking pinned sessions.
Add regression coverage for default-only heartbeat.session pins and explicit agent heartbeat entries that inherit the default session.
Validation:
- pnpm test src/commands/doctor-heartbeat-session-target.test.ts
- pnpm tsgo:core
- pnpm tsgo:core:test
- pnpm config:schema:check
- pnpm exec oxlint src/commands/doctor-heartbeat-session-target.ts src/commands/doctor-heartbeat-session-target.test.ts
- pnpm exec oxfmt --check src/commands/doctor-heartbeat-session-target.ts src/commands/doctor-heartbeat-session-target.test.ts
- git diff --check
Beads: openclaw-8zp
* test(heartbeat): avoid redundant doctor assertion (review feedback)
The CI lint shard flags the non-null assertion in the heartbeat doctor regression test. Keep the same test setup while using an explicit guard so the test still narrows the fixture before mutating the heartbeat entry.
Validation:
- pnpm exec oxlint src/commands/doctor-heartbeat-session-target.test.ts
- pnpm test src/commands/doctor-heartbeat-session-target.test.ts
- pnpm tsgo:core:test
- git diff --check
Beads: openclaw-8zp
* docs(config): refresh baseline after heartbeat branch update
* fix(heartbeat): narrow doctor session warnings (review feedback)
`session_end` was only fired when a session was replaced, reset, deleted, or
compacted -- the gateway shutdown/restart paths closed the process without
enumerating active sessions, so downstream `session_end` plugins
(e.g. claude-mem) accumulated ghost rows in `active` state across restarts.
Issue reporter saw 11 orphaned sessions cause 63 timeouts/day from agent
pool exhaustion.
Add an in-memory active-session tracker
(`src/gateway/active-sessions-shutdown-tracker.ts`) populated by
`emitGatewaySessionStartPluginHook` and forgotten unconditionally by
`emitGatewaySessionEndPluginHook` (even when no plugin listens), so any
session that has already been finalized through the normal lifecycle is
never re-fired by the shutdown drain. The close handler then calls a new
`drainActiveSessionsForShutdown({ reason })` in `session-reset-service.ts`
between the `gateway:shutdown`/`gateway:pre-restart` lifecycle hooks and
the subsystem teardown steps; the drain races a bounded 2 s total timeout
so a slow plugin cannot block SIGTERM/SIGINT, surfacing the timeout as a
`session-end-drain` warning on the shutdown result.
Extend `PluginHookSessionEndReason` with `"shutdown"` and `"restart"` so
plugins can distinguish a graceful close from a planned restart; the close
handler picks `restart` when `restartExpectedMs` is set and `shutdown`
otherwise. Update `emitGatewaySessionStartPluginHook` to also accept
`storePath`, `sessionFile`, and `agentId` so the shutdown drain can build
the same `session_end` payload shape the normal lifecycle path emits, and
update the existing call sites in `session-reset-service.ts` and
`server-methods/sessions.ts` to pass those fields through.
Tests:
- `src/gateway/active-sessions-shutdown-tracker.test.ts` (new) -- tracker
insert/forget/clear semantics, idempotent re-noting, empty-id guard,
snapshot isolation.
- `src/gateway/drain-active-sessions-for-shutdown.test.ts` (new) -- drain
fires `session_end` with the right reason for every tracked session,
skips sessions already finalized via reset/delete/compaction, and still
forgets sessions even when no `session_end` plugin is registered.
- `src/gateway/server-close.test.ts` -- four new cases covering the
shutdown/restart drain wiring, the bounded timeout warning, and the
drain-skipped-when-no-helper case.
Docs:
- `docs/plugins/hooks.md` documents the new `shutdown`/`restart` values
on `PluginHookSessionEndReason`.
- `docs/automation/hooks.md` documents the post-`gateway:shutdown`
`session_end` drain step and its bounded execution guarantee.
Fixes#57790.
Route group/channel task, subagent, and media completions through one requester-session delivery policy, including plugin legacy session keys.
Also keeps current Zalo lifecycle test typing green on CI after the latest main changes.
Co-authored-by: Merlin <merlin@funcracker.net>
When an automatic compaction happens mid-turn, chat users currently see a long stall and the run can finish without a final visible answer.
This adds an optional bundled compaction notifier hook and a one-shot compacted-transcript continuation retry when a compaction produced no user-visible final payload.
Keep async music generation completions on the requester-session wake path even when direct-send completion is enabled.
Also aligns config help, generated schema text, public docs, and the changelog so tools.media.asyncCompletion.directSend no longer claims to direct-send music completions.
Verification:
- pnpm test src/agents/tools/music-generate-background.test.ts src/agents/tools/video-generate-background.test.ts
- pnpm exec oxfmt --check --threads=1 src/agents/tools/media-generate-background-shared.ts src/agents/tools/music-generate-background.ts src/agents/tools/music-generate-background.test.ts src/config/schema.help.ts src/config/types.tools.ts docs/automation/tasks.md docs/gateway/config-tools.md CHANGELOG.md
- pnpm config:schema:check
- pnpm config:docs:check
- pnpm check:changelog-attributions
- git diff --check
- OPENCLAW_TESTBOX=1 pnpm check:changed