* refactor(qa): route live channel selectors through suite host
* fix(qa): repair live selector CI
* fix(qa): remove retired runner exports
* fix(qa): remove obsolete live evidence
* fix(agents): wake owning session after generated-media direct delivery
When a background media generation (image/music/video) completes but the
requester's agent turn cannot be woken, delivery falls back to sending the
media straight to the channel. The owning session never learned about it,
leaving the attachment orphaned with no agent follow-up.
Queue a system event plus a scoped heartbeat wake after both direct
fallback paths (announce delivery and the shared background lifecycle) so
the agent continues the conversation in its own voice. Subagent requester
sessions skip the heartbeat since their completions route via announce.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(agents): persist generated media session handoffs
Co-authored-by: Molty <steipete@gmail.com>
* chore: prune max-lines baseline
* fix(agents): harden durable media handoffs
* fix(agents): charge media retries once
* chore: refresh max-lines baseline
* fix(agents): persist delivery settlement cleanup
* fix(agents): fence interrupted media delivery
* fix(agents): fence durable handoff admission
* fix(agents): reconcile terminal handoffs at retry limit
* fix(agents): align durable handoff types
* test(agents): type durable handoff fixtures
* fix: satisfy session delivery lint
* fix: avoid payload map spreads
* fix: satisfy durable handoff gates
* test: align generated media handoff expectations
* fix: avoid serializing session recovery state during load
---------
Co-authored-by: Molty <steipete@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(process): report actual UTF-8 byte count in stdin write message
Replace string.length (UTF-16 code units) with Buffer.byteLength(content, 'utf8')
so the reported byte count matches the actual bytes written to process stdin.
For ASCII content the values are identical. For non-ASCII content (CJK, emoji),
string.length underreports the actual UTF-8 byte count.
* test(process): cover UTF-8 stdin write byte count
Co-authored-by: 陈志强0668000989 <chen.zhiqiang1@xydigit.com>
* style(test): keep UTF-8 regression compact
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(process): report actual UTF-8 byte count in send-keys message
Replace string.length (UTF-16 code units) with Buffer.byteLength(data, 'utf8')
so the reported byte count matches the actual bytes sent to process stdin.
For ASCII key sequences the values are identical. For non-ASCII text
sent via literal key data, string.length underreports the actual UTF-8
byte count.
* test(process): cover UTF-8 send-keys byte count
Co-authored-by: 陈志强0668000989 <chen.zhiqiang1@xydigit.com>
* ci: prune stale max-lines baseline
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(agents): reject synchronous sessions_send self-targets, break down missing-cost entries, dedup usage merges
- sessions_send fails fast with a clear error when a synchronous send resolves
to the calling session's own key, instead of enqueueing behind the sender's
own lane until timeout and falling back to an empty reply; fire-and-forget
(timeoutSeconds: 0) self-delivery keeps working (#107172)
- missingCostEntries now carries a provider/model breakdown surfaced on the
status runtime line and gateway CLI cost line, so zero-priced usage (e.g.
openai-codex/*) is attributable instead of an opaque counter (#98348)
- codex-synthetic-usage merge helpers share one precedence helper; behavior
unchanged, duplicate ranking logic deleted (#107497)
* test: use a valid billing type in synthetic-usage precedence case
* test: fix billing expectation to match valid type
* fix(plugins): keep official plugin config across bundled-to-external moves, harden npm metadata parsing
- doctor --fix and plugin auto-enable treat official-catalog plugin ids as
known configuration even when the external package is not installed yet, so
a bundled-to-external transition (codex) no longer silently drops the
plugins.allow entry and unregisters the agent harness; garbage ids are still
pruned, and the codex-specific diagnostic suppression in the doctor scan is
replaced by the generic official-catalog rule (#107226)
- npm view metadata normalization handles object and multi-version array
output, flat dist.* keys and nested dist objects, absent openclaw blocks,
selects the maximum satisfying semver (publication order is not semver
order), fails closed when a recognized range has no satisfying entry, and
names the missing fields in the error (#107842)
The #107219 register-crash fix (lazy binding-store opening so plugin
registration never touches runtime.state under the base runtime) landed with
#108311 alongside its regression test.
* style: format install-source-utils imports
* fix(plugins): align hook and tool registrations
Reuse gateway-owned plugin registrations for matching hooks and tools while loading only missing tool owners from narrower runtime scopes.\n\nCo-authored-by: w33d <w33d@steadholme.local>
* test(plugins): cover mixed registry tool owners
Verify gateway-pinned and compatible active registrations compose without another plugin load.
Co-authored-by: w33d <w33d@steadholme.local>
* refactor(plugins): keep pinned registry lookup internal
Reuse the existing runtime-state contract so hook and tool ownership does not expand the Plugin SDK surface or treat unpinned active registries as Gateway owners.
* test(plugins): complete hook context fixture
Supply the required tool name in the stateful hook ownership regression context.
* chore: leave contributor release note in PR
Normal contributor PRs do not modify the release-owned changelog; the PR body retains the release note and attribution.
* fix(plugins): align partial registry owners
* fix(plugins): preserve scoped tool diagnostics
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: w33d <w33d@steadholme.local>
* fix: treat loopback bind as local-only in doctor security
* test: type resolveGatewayBindHost mock for check-test-types
* fix(gateway): keep loopback bind canonical
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
* fix(web-fetch): recognize mixed-case media types
* fix(web-fetch): match normalized media types
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Move the Codex-specific PreToolUse loop relay switch into the Codex
plugin, preserve policy relays, and cover both normal and side turns.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: marchpure <marchpure@users.noreply.github.com>