* fix(cron): use direct lookup instead of paginated search in cron edit
* fix(test): update cron-cli tests to mock cron.get and remove obsolete pagination checks
* fix(cron): preserve edit compatibility with older gateways
* fix(cron): preserve legacy lookup error cause
---------
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(cron): accept null fallbacks in cron update patch payload
createCronPatchObjectSchema passes nullableStringArraySchema for model and
toolsAllow, but fallbacks was still hardcoded as a non-nullable array in
cronPayloadObjectSchema, rejecting null clears before they reach the
Gateway service layer.
Switch fallbacks to a parameter so the patch context can pass the nullable
variant, matching the existing pattern for model and toolsAllow.
Fixes#100707
Co-Authored-By: Claude <noreply@anthropic.com>
* test(cron): cover model+fallbacks null clear in patch schema test
---------
Co-authored-by: Claude <noreply@anthropic.com>
Gateway (additive, no protocol version bump): SessionEntry gains
lastReadAt/markedUnreadAt/lastActivityAt; session rows expose a derived
unread flag (explicit mark, or last read before latest activity; never-read
sessions stay read so upgrades do not light up). lastActivityAt is stamped
in the canonical post-run store update - user, channel, and cron runs count
as activity; heartbeat, internal-event, and preserved-state runs do not.
sessions.patch gains unread; sessions.create gains fork (transcript fork
from parentSessionKey under the parent lifecycle lock, refusing active,
concurrently-changed, and oversized parents, cross-agent aware).
Web sidebar: Pinned/custom-group/Ungrouped sections, unread dots, kebab and
right-click context menu (pin, mark unread/read, rename, fork, move to group,
archive, delete guarded for agent main sessions and active runs), mark-read
on view with loop-safe re-acknowledgement and failure retry; sessions page
gets unread + fork actions and shared custom-group helpers.
iOS Command Center: grouped sections, unread/pin indicators, Show Archived
gated on per-entry state, full context menu with rename/new-group alerts and
delete confirmation, current-session preview guarantee, read-episode
re-acknowledgement; new patch/delete/fork transport calls; Swift protocol
models regenerated.
Android SessionsScreen: grouped headers, unread/pin indicators, Archived
filter gated on per-entry state, long-press menu with the full control set,
agent-scoped forks, explicit label/category clears from session events,
main-session fallback when archiving/deleting the open chat, read-episode
re-acknowledgement with failure retry.
Closes#100739
* fix(auto-reply): warn when /export-session only contains user messages (backend-delegated)
Closes#90844 (minimum-fix option 2).
When a session is driven by a CLI/ACP backend, OpenClaw's own transcript only
records the inbound user messages. /export-session would still produce a
successful HTML export with empty summary stats and no assistant/tool/usage
data, which is misleading.
This change detects the backend-delegated case (a transcript whose message
entries are exclusively role: user) and surfaces a clear warning in the command
reply text and the exported HTML header.
* fix(auto-reply): correct template literal closure in export session HTML
* fix(auto-reply): warn on backend-delegated session exports
* fix(session): harden backend export warning
* fix(session): read persisted ACP export metadata
* fix(session): keep ACP metadata lookup best-effort
* fix(session): avoid shadowed export locals
* test(session): type export store mock
---------
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
* feat: correlate native search outcomes in audit history
Metadata-only audit ledger for agent runs and tool actions in the shared
state DB: stable event identity, closed action/status/error vocabularies,
one-way-hashed tool-call ids, never-inferred terminal outcomes for native
web-search (explicit completed/failed only; otherwise unknown), bounded
retention, audit.list gateway RPC and openclaw audit CLI. Squashed from
the 82-commit audit stack for replay onto current main.
* feat(audit): add audit.enabled config gate (default on)
The metadata-only audit ledger records by default: an audit trail enabled
only after an incident cannot explain the incident, and the rows are
strictly less sensitive than the transcripts every install already
stores. audit.enabled=false stops new writes at the gateway subscription
seam; audit.list and openclaw audit keep serving existing records until
they expire. Documented in the configuration reference, protocol page,
and CLI reference.
* fix: repair full-matrix CI findings after rebase
- break the dynamic-tools/dynamic-tool-execution import cycle by
extracting resolveCodexToolAbortTerminalReason into a leaf module
- restore main's session-worktree protocol exports lost in the
index.ts auto-merge
- register the audit event writer worker as a knip entry point
- docs table formatting; subagent wait-cancellation test scoped to its
audit intent (outcome + timing) and advanced past main's new
lifecycle-timeout retry grace
* fix: release stale reply work during reset cleanup
* fix: release archived reply runs during reset
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>