Keep SessionManager cache and guard pairing aligned with the committed redacted transcript. Settle committed pending-call state before persistence callbacks, retaining pending calls when the append fails. Covers the false aborted result found in live Buzz message-tool testing.
Expose opt-in replyToMode off while retaining threaded replies by default. Keep incoming thread/session identity and explicit tool or CLI targets intact. Resolves#120339. Thanks to @Alfridus1 for the report.
* feat(reef): operator-configurable sharing rules for the guard
Adds channels.reef.guard.rules with capped outbound/inbound free-text
policy. Rules ride the trusted instruction side of the guard call only,
may tighten decisions or explicitly allow otherwise-review cases, and can
never override the deny floor or deterministic checks. The rules text is
hashed into the effective policy version so audit rows and pending review
approvals bind to the exact policy in force.
* fix(reef): full rules digest in policy identity; align blank-rule validation
ClawSweeper review fixes: use the untruncated sha256 rules digest in the
effective policy version so approvalDigest stays collision-resistant, and
express identical non-blank (\S) rule validation in the zod schema, the
manifest JSON Schemas, and the generated channel metadata instead of a
trim-transform mismatch.
* refactor(imap): consume the core identifier-authentication scale
Use the SDK type and canonical strength comparator instead of the private
SenderStrength vocabulary and index ordering. Bind config values to the SDK
union with a compile-time exhaustiveness check, preserving all config keys.
Classify unproven From ownership, including no-evidence and DMARC temperror
results, as unverified. Only an explicit unverified minimum gains admission;
the default verified floor and asserted minimum keep their behavior. Keep
existing token admission and thrown-authenticator retries unchanged.
Document the remaining mutable token/early-rejection paths and expose only
the canonical comparator through the SDK, with packaged-consumer coverage.
The IMAP introduction has no stable release contract.
* docs(security): record landed sender-auth mitigations in the threat atlas
Record the graded exact-pair identifier-authentication gate and inert mutable
allowFrom audit findings. Mark R-008 implemented in core while retaining
per-channel verified adoption and downstream mappers as remaining work.
Keep the existing atlas structure and Medium residual risk.
The table was fitted on 2026-08-23 and has rotted. Measured across the
checks-ui-e2e logs of runs 33063115103 and 33055390669, the suite has grown from
247 to 281 files and from 1430s to 2422s of body, and every surviving hint now
reads 1.5-1.9x low (chat-tool-turn-outcome 17s -> 32s, workspace-validation
19s -> 33s, chat-rail-columns 25s -> 36s). The new slowest file,
chat-flow.clipboard at 49.6s, was not listed at all.
Stale low hints are worse than no hints: the packer treats those files as cheap
relative to byte-proxied ones and stacks them together. Replaying the measured
per-file medians, the widest control-UI shard packs at 243s under the current
table against a 220s ideal, and 233s once refreshed.
Regenerated from measurement rather than patched, and widened from 31 to the 80
slowest files so the table covers the suites that actually set the tallest
shard. Everything below rides the byte proxy, which is fine for the ~4s median
file but mispredicts by up to 3.6x on the tail.
After a reconnect lost the chat.send ack, the outbox reconcile only accepted
the transcript idempotency marker as delivery proof, so a send whose run was
actively streaming parked as a red 'Delivery uncertain' composer chip for the
whole run. The reconcile now also retires a queued send when the session row
reports its run id in activeRunIds or as lastRunId — the same fact live
terminal-event retirement already trusts.
Attempted unconfirmed messages now stay in the conversation as ordinary
bubbles with an amber 'Delivery unconfirmed · Retry' footer (failed keeps the
red 'Not sent'); the duplicate pane banner is suppressed for them since the
bubble owns the outcome. Command chips, never-attempted failures, and storage
errors keep their existing surfaces. Calmer copy for the remaining honest
uncertainty case.
* fix(twitch): retain native sender identity in execution audits
Forward the registered channel runtime and actual account identity, keeping native participants distinct from role authorization. Normalize the all role at the Twitch policy producer and preserve unknown and disabled-collection paths.
Cover actual registered-plugin ingress and native reply delivery, and drain asynchronous monitor test work before cleanup. Related to #122863; no shared authorization or storage change.
* test(twitch): track the registered context builder in inventory
* test(twitch): honor host and plugin contract boundaries
Both halves of the docs publish starvation bug (openclaw/docs b4b130bd8,
#131155) were discovered by noticing stale published docs, not by any alert:
nothing watched whether the openclaw/docs mirror actually tracked docs-touching
commits on main. A broken sync (dead token, MDX failure, disabled workflow,
GitHub incident) would again go unnoticed.
Add a scheduled Docs Mirror Freshness check (every 30m) that parses the watched
paths from docs-sync-publish.yml itself - so the staleness definition can never
drift from the sync trigger - finds the newest docs-touching main commit via
the commits API, and compares it against the mirror's .openclaw-sync/source.json
SHA. When the mirror trails by more than 60 minutes it dispatches one
docs-sync-publish recovery run (skipped when a sync is already queued or in
progress) and fails the run so the workflow actor is notified.
The check lives in openclaw/openclaw rather than openclaw/docs because the path
filters it must judge against live here, and same-repo workflow_dispatch heals
with the default GITHUB_TOKEN instead of a cross-repo PAT.
Live-proven: fresh path against the real repos; stale path (detection,
active-run suppression, failing exit) via a simulated stale mirror SHA;
recovery dispatch endpoint via a real manual sync run (33113089552).
Replace the drain waiter array + release loop with one lazily created
shared idle deferred (same semantics: concurrent waiters share it, it
resolves on the first all-trackers-zero publish), and fold the tracker
update into publishInboundPendingWork.
Collapse expectInboxPairingReplyText into expectPairingPromptSent: the
mocked pairing upsert always issues PAIRCODE, so the regex code
extraction and code-override parameter were dead generality. Net -20
lines of test-support code, no behavior change.
Declare the provider-supported efforts and reuse the canonical minimal-to-low mapping for static GPT-5.4 mini resolution. Preserve xhigh and keep max unavailable.
Every docs-touching push to main cancelled the in-flight docs-sync-publish
run (per-ref concurrency group with cancel-in-progress: true), and cancelled
runs leave no successor. Under sustained merge velocity the openclaw/docs
mirror never advanced: observed live 2026-08-27 as four consecutive
'completed cancelled' runs while the mirror sat 6 commits behind main.
Queue instead of cancel: GitHub keeps only the newest pending run per
concurrency group, so bursts still collapse to one follow-up run, and the
existing skip_stale_source guard keeps back-to-back completions idempotent.
This is the source-to-mirror half of the docs publish starvation bug; the
mirror-to-R2 half was fixed in openclaw/docs b4b130bd8.
Run hidden Skill Workshop reviews on a private detached session so foreground messages stay responsive and isolated. Preserve prompt-cache affinity, remove closed delivery authority, and retire queued evidence before asynchronous preparation.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Declare the Gemini Chat Completions transport and request compatibility in the owning model manifest. Remove the private metadata decoration loop so static catalog selection and forward-compatible synthesis use the same declared contract.
* fix(openshell): unregister sandbox backend on plugin stop
Bind the explicit backend disposer to the plugin service lifetime so disabling or reloading OpenShell retires its factory, manager, and workdir hooks together. Preserve the core registry's stale and repeated disposer semantics.
* fix(sandbox): retire plugin backends with registry lifecycle
Introduce on admitted bot joins using the existing sealed no-tools turn and durable room dedupe. Matrix uses room metadata and readable history; LINE uses group names and explicitly unavailable history.
Mark Matrix bridge membership provenance without changing existing event delivery, invite handling, or auto-join. Exclude startup snapshots and already-joined profile updates, including startup connection recovery.
Simplify snapshot budget accounting while preserving prompt bytes, metadata order, and oldest-first message dropping. Add channel config, docs, and regression coverage.
* feat(configure): surface the trusted-proxy loopback opt-in with its warning
Ask for explicit consent before enabling same-host trusted-proxy authentication,
and explain the runtime rejection when consent is declined. Preserve existing
loopback consent and unprompted device enrollment policy on same-mode reruns.
Reuse runtime loopback classification, add English and Chinese wizard copy,
and document the consent and preservation behavior.
* test(configure): assert wizard auth through the real builder
Remove the auth-builder mock and replacement factories so gateway prompt tests verify returned configuration across proxy, token, password, and SecretRef flows. Retain all consent regressions while reducing test scaffolding and reusing tracked environment cleanup.
* fix(openshell): preserve nested host symlinks during mirror sync
Reconcile mirror entries recursively so trusted host symlinks and their ancestors survive remote edits and deletions. Preserve unlink-before-copy hardlink safety and drain pending filesystem work before returning an error. Cover the repair with unit regressions and the real OpenShell E2E flow.
Fixes#131111
* chore(openshell): satisfy mirror callback lint rules
* feat(security): warn on inert mutable allowFrom entries
Report configured entries that cannot authorize with name matching disabled,
and preview lockout counts before disabling mutable matching. Distinguish
mutable aliases from exact identifiers with unproven ownership in audit text.
Reuse channel ingress declarations through one SDK classifier without changing
admission policy. Keep Discord audit findings redacted and exclude symbolic
access-group references from mutable-identifier warnings.
Refs #131099.
* test(security): keep entry-authentication audit coverage in its lanes
* fix(canvas): retire the legacy document root only after migration completes
* fix(canvas): preserve older migration roots and canonical aliases
Read both historical host locations with shipped plugin precedence.
Select legacy config owners from existing manifest metadata for doctor,
without broadening session-store ownership. Recognize realpath aliases
of canonical storage and cover persisted partial repairs and retries.
* fix(agents): continue settled tool batches after a transport drop
A transient provider transport failure (WebSocket drop, socket reset) that
lands after every tool call in the batch has settled used to kill the turn:
any executed side-effecting tool marks the attempt replay-unsafe, and every
recovery path is gated on replay safety, so the runner surfaced the generic
"Agent couldn't generate a response" warning even though the tool results
were already persisted and nothing needed to be re-run. Under code mode every
tool call is exec, so any turn with a tool call died on a socket hiccup.
Continue such attempts from the persisted transcript with the existing
mid-turn continuation prompt, bounded to two continuations per run and only
for silent errored turns with transient evidence; prompt resubmission, profile
rotation, and model fallback stay closed for side-effecting attempts.
* fix(agents): narrow settled transport recovery
Require provider transport diagnostics before continuing a replay-unsafe settled tool batch, leaving rate-limit failures with the existing failover owner. Preserve the prior last-call usage only when a compaction retry fails before recording a replacement, without overwriting a newer successful call after later processing errors.
* fix(agents): restore retry usage only on failure
Keep the previous exact usage hidden while a compaction retry is active. Restore it only when the retry terminates with an error before recording a new call; a successful replacement call remains authoritative across later processing failures.
* fix(agents): require settled tools for transport resume
Keep the parked Code Mode exception scoped to overflow recovery. Provider transport recovery now requires every tool lifecycle item to be settled, with regression coverage for a suspended nested Code Mode run.
* fix(agents): fence suspended code mode recovery
Reject transcript continuation whenever the settled batch still carries producer-recorded suspended Code Mode work, even if the outer lifecycle count has reached zero. Cover that exact state in the recovery regression.
* fix(agents): resume parked code mode after transport drop
Use the canonical mid-turn settled evidence for transport continuation so producer-recorded parked Code Mode runs can resume from the current transcript. This lets the model call wait for the existing cell without replaying the original prompt or exec.
Cover parked active-count states and preserve the terminal, abort, timeout, visible-output, diagnostic, rate-limit, retry-budget, and no-fallback gates.
Worked on by:
- @VACInc
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
---------
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
* fix(configure): preserve the primary model across provider auth overrides
* test(configure): cover real model policy after provider auth
Replace copied model policy transforms with the production implementations so configure coverage preserves model metadata and exercises target projection. Cover string primaries and fallback-only initialization without changing production behavior.
* fix: honor scenario drivers in generated QA commands
Carry declared driver requirements through coverage search, grouping and quoted command output. Preserve unconstrained defaults and validate generated arguments through real CLI parsing and canonical lane selection. Closes#131088.
* test: capture generated QA commands through the shell