- Rename openclaw-test-audit skill to test-audit; add an authoring-gate mode
invoked whenever tests are written, not only during sweeps.
- Repair Doctrine: capture the failing repro before editing; regression tests
must fail on pre-fix code. Bug fixes default to net <=0 production LOC via
the refactor that absorbs the fix, not a bolted-on guard.
- ClawSweeper policy: production-vs-test LOC reviewMetrics entry is now
unconditional for code PRs, counted with judgment; net-positive bug-fix
deltas become risks findings with bestSolution naming the absorbing refactor.
* fix(agents): pair reset tool results within retained session history
## What Problem This Solves
Session resets selected tool-call pairs from history preceding the retained-session boundary, allowing an excluded call to incorrectly claim a retained tool result and leaving replayed conversation history inconsistent.
## Why This Change Was Made
The session-context owner now identifies the retained range before pairing reset tool calls and results. Both reset and compaction flows reuse the same canonical bounded history slice, removing duplicate scan and membership logic.
## User Impact
Reset agent sessions retain only legitimate in-window tool exchanges, repeated resets remain consistent, and cloud-worker replay receives coherent session context without resurrecting discarded calls.
## Context
Actual production-source execution reproduced the previous failure and passed after the fix across valid in-window pairs, repeated resets, and cloud-worker boundaries. Focused session-context and worker-launcher regressions cover the owner and downstream consumer. Existing oxfmt formatting and scoped whitespace checks passed; production code decreases by five lines.
* test(gateway): cover reused reset tool call ids
Operators who disabled the GPT-5 friendly interaction style now keep that preference after openclaw doctor --fix. Existing OpenAI plugin personality config remains authoritative.
Recognize Crabbox workload-routing provider exhaustion as a pre-dispatch backend outage so check:changed runs its documented local fallback.
The observed full provider-chain outage previously exited 2 without running local lanes.
The existing command-exit veto still runs first, so a remote run that actually executed and failed remains fail-closed.
Worker live events rejected tls_certificate fallback payloads because duplicated closed reason lists had drifted. Establish one canonical dependency-light fallback vocabulary and share its explicit TypeBox schema across worker and cron protocol boundaries.
Centralize global session subscription keys by agent, preserve the default-agent raw global compatibility path, and let authoritative observer audiences reach their selected sockets without changing the public gateway broadcast contract.
* feat(ui): float task-suggestion cards top-right with copy-prompt action
- Float a compact tray in .chat-main__conversation with absolute positioning, min(400px, 100% - margins) sizing, elevation, and internal scrolling.
- Remove the icon column, keep dismiss in the header row, and move a compact split button to the bottom-right.
- Add Copy prompt to the menu via shared copyToClipboard, copying the raw prompt while display-only sanitization remains documented inline.
Release note: Suggested-task cards now float as compact cards at the chat top-right and offer Copy prompt in the action menu.
* style(ui): neutral grey task-suggestion card and actions
Drop the accent-tinted card border/background, mute the eyebrow, and use default grey button treatment for the split control per operator direction.
* fix(ui): ungate copy-prompt and surface clipboard outcomes
- Menu now always renders with the client-local Copy prompt while acceptance-mode items stay capability+scope gated (addresses ClawSweeper finding 1).
- Copy success shows a transient Copied label and failures surface through the pane error path (finding 2).
- Task-suggestion pane logic extracted to chat-pane-task-suggestions.ts and the tray adapter moved into the component to keep files under the 700-line cap.
* fix(ui): test task suggestions through tray adapter
* test(ui): cover task-suggestion clipboard failure
* test(ui): split task-suggestion pane coverage
* chore(ui): raise startup JS budget for task-suggestion card feature
QA-profile measurement was 324617-324620 B versus the 324608 B effective budget; this owner-directed PR #121259 bump follows the baseline file’s documented feature-growth precedent.
* chore(ui): raise startup JS ceiling to 318 KiB for task-suggestion cards
The fixed 317 KiB ceiling (324608 B) was within ~20 B of CI-measured startup bytes after accumulated main drift; the task-suggestion card feature crossed it. Ceiling raised with in-file maintainer-approval comment per its own convention; ratchet baseline set to CI-measured 324626 B.
* fix(ui): keep task-suggestion copy available read-only
Remove the stale accept-or-dismiss tray guard now that Copy prompt is a client-local action. Keep Gateway-backed accept and dismiss controls independently gated, with a regression for operators who can only list suggestions.
* test(ui): cover list-only task-suggestion copy
Update the mocked-Gateway E2E to match the repaired read-only behavior: the suggestion remains visible, its mutating Start action is disabled, and Copy prompt stays available.
* fix(ui): scope the Control UI cursor convention to app-like display modes
The app-chrome cursor convention from #103357/#103411 was applied
unconditionally, so an ordinary browser tab lost the pointer hand on
buttons, menus, tabs, rails, selects and accordion summaries — the only
hover affordance a page owns. The convention is correct for the installed
window the manifest declares ("display": "standalone"), not for every
window the same bundle is served into.
base.css now owns one policy token, --cursor-action, selected by display
mode: pointer by default, the desktop arrow under standalone, minimal-ui
and window-controls-overlay. A low-specificity rule maps generic
actionable controls onto that token, restoring the affordance on the
surfaces #103411 stripped bare, while every component rule that owns a
semantic cursor (not-allowed, disabled, grab, resize, zoom-in, text,
wait) keeps winning without !important.
The 92 cursor: pointer declarations that had drifted back into ui/src
since July now consume the token instead of hardcoding the hand, so they
stop contradicting the policy in an installed window. Real hyperlinks
keep the pointer in every mode. The pre-boot mount fallback repeats the
policy locally because it must render when the bundle fails to load.
Closes#121242
* test(ui): run the cursor policy browser test in the node-driven project
ui/vitest.config.ts routes Playwright-from-Node .browser.test.ts files to the
unit-node project; without registering the new cursor policy test there, the
in-browser chromium project tried to import it and failed on node:fs/playwright.
* fix(ui): keep the desktop arrow in the native app hosts
The macOS dashboard embeds the Control UI in a plain web view, which
reports `display-mode: browser`, so the display-mode-only policy would
have handed it the browser-tab pointer. It already announces itself with
`openclaw-native-macos`/`-nav`/`-web-chrome` on `<html>`, the same markers
`ui/src/styles/layout.css` matches on, so the policy reads those too.
* fix(agents): keep requester settle attached to live children
* fix(agents): gate requester settle on terminal children
---------
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
* fix(agents): bind terminal polls to exact process
UUID-owned completion receipts and ProcessSession-bound finished snapshots prevent same-slug successor consumption.
* chore(plugin-sdk): refresh API baseline
Refresh declaration-closure hashes for the internal system-event receipt boundary.
Resolve pnpm's configured modules directory from the checkout root before TypeScript boot, preserving both environment spellings and canonical checkout/common-worktree fallbacks. Use Node package self-resolution from the hydrated tsx package so nested wrappers cannot change relative path semantics.
* fix(ui): confirm Devices pairing rejects and token revokes in-app
Reject device pairing, reject node pairing, and revoke device token asked for
confirmation through native window.confirm from the shared Nodes operations
module. Embedded webviews without a dialog bridge return false for that call,
so all three actions ended with no dialog, no request, and no recorded reason.
Move the confirmations to DevicesPage, the visual owner, onto the canonical
showConfirmDialog helper already used for inventory removal, and give the copy
real i18n keys. The shared operations module now presents no UI at all.
* test(ui): drive the revoke confirmation through the in-app dialog
device-token-reconnect drove the revoke prompt through Playwright's native
dialog event, which no longer fires now that the page owns the confirmation.