Commit Graph

77676 Commits

Author SHA1 Message Date
Vyctor H. Brzezowski bb02fc53ea fix(ui): make chat inline code readable on dark themes (#121376)
Every dark palette defines --secondary with the same hex as --card, so the
markdown code chip painted with --secondary collapsed into the surface it sat
on (1.00:1 against a user bubble, 1.06-1.08:1 against the flat assistant
column) and --border was too close to the background to draw an edge. Light
mode never showed the bug because it overrode both properties.

Promote the light override into the single canonical rule: code chips and code
blocks paint --bg-muted with a --border-strong edge in every theme, and the
mode-specific overrides (including the raw rgba border) are deleted.

Also fixes the theme-contrast guard, which merged repeated `:root` blocks by
overwriting instead of merging, so the default `dark` theme resolved to an
empty token map and skipped every assertion. A new case reads the chip tokens
out of the shipped rule and asserts surface and border separation from --card
and --bg on all six themes.
2026-08-10 01:18:23 -03:00
ClawSweeper 4fe078fcd8 fix(cli): stop emitting retired wide-area config (#121392)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-09 21:15:24 -07:00
Vyctor H. Brzezowski 1512dd88cb fix(ui): sidebar pin and unpin now respond immediately instead of waiting on the Gateway (#121254)
* fix(ui): pin sidebar sessions optimistically in the mutation owner

Pin/unpin had no visible outcome until `sessions.patch` and the canonical
`sessions.list` refresh both landed: the row, its icon, and its section kept
the pre-click value for the whole round trip.

`createSessionMutations.patch` already owns an optimistic/rollback lifecycle
for model overrides, and the capability already exposes `patchRowLocal`, but
no pin path used it. Give the pin its own pending intent in the same owner:
flip the published row up front, chain `previous` through overlapping patches
so a rollback lands on the last Gateway-confirmed value, and let the newest
intent win when an older completion's list refresh republishes stale truth.
Retiring the connection or disposing the capability drops pending intents.

Every pin surface routes through this one operation, so the sidebar button,
the row menu, sidebar drag/drop, and the Sessions page all get the same
feedback and the same rollback. A rejected zone drop still writes no sidebar
slot: `handleSidebarZoneDrop` persists only on `completed`.

Closes #121247

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* test(ui): return only the pin harness fields the cases use

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(ui): re-assert pending pin intents on canonical session rows

A sessions.changed event during a pin/unpin round trip queues a canonical
list replacement, and every Gateway session payload carries the server's
pre-patch pinned/pinnedAt. The optimistic row was therefore reverted to the
pre-click value until the patch resolved, restoring the no-feedback bug.

The session capability already has one seam where canonical rows become
published rows, so the pending pin joins swarm notes there instead of being
a write the next refresh can lose. Settling no longer republishes a newer
intent by hand; it only hands that intent the baseline the Gateway confirmed.

The optimistic write now moves pinned and pinnedAt together, matching the
Gateway (which derives pinned from pinnedAt) so an in-flight row cannot sort
into a slot the server would never produce.

* fix(ui): publish pin intents to every session list

The optimistic write only reached the primary session snapshot. The archived
and all sidebar filters keep their own published lists, so pinning from
either one still waited on the Gateway, and a canonical refresh landing
inside the patch window could leave them on a value the rollback never
corrected.

Both the intent and its rollback now republish through the roster's
decoration seam, so every held list lands on the same value in one pass and
a failed pin needs no extra canonical list to settle.

* fix(ui): take the pin rollback baseline from the published row

The rollback baseline came from the primary session snapshot alone. A
sidebar on archived or all renders its own subscribed list, so a row shown
only there recorded an unpinned baseline; a rejected unpin then rolled it
back to that guess and left a session the Gateway still has pinned looking
unpinned, with no refresh to correct it.

The roster owns every published list, so it answers where a row currently
is, and the mutation owner captures the baseline from that row.

* fix(ui): move a superseded pin's baseline to confirmation time

An overlapping intent's rollback baseline was rebased only after the older
patch's list refresh returned. A rejected unpin landing in that gap rolled
back to the pre-pin value, and if the refresh then failed the row stayed
unpinned while the Gateway held the pin.

The Gateway has committed once the patch resolves, so the baseline moves
there instead.

* docs(ui): record why pin intents need no rollback on connection retirement

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 01:06:48 -03:00
Peter Steinberger 232281fc74 perf(skills): reuse unchanged sandbox skill snapshots (#121379)
Gate reuse on the watcher-owned snapshot version and persisted entry manifest, while keeping safe paths process-owned and reconciling only changed skills.

Cache config fingerprints by object identity and reset them at the applied-config lifecycle owner.
2026-08-09 21:00:05 -07:00
Peter Steinberger 592bf90b07 perf(workers): cut repeated full-tree workspace hashing (#121365)
* perf(workers): reuse workspace hashes during reconcile

* chore(workers): drop one-off sync benchmark harness
2026-08-09 20:50:08 -07:00
Peter Steinberger 374007083a fix(mac): adopt CLI identity during state migration (#121313)
* fix(identity): one canonical device-identity contract across app and CLI

* fix(ci): satisfy native identity checks

* chore: drop changelog edit (release-generation owns CHANGELOG.md)
2026-08-09 20:47:21 -07:00
Peter Steinberger 1367e9a79f refactor(packages): collapse duplicate type surfaces (#121340)
* refactor(packages): collapse duplicate type surfaces

* chore(generated): refresh package contract artifacts
2026-08-09 20:45:15 -07:00
Sarah Fortune 176716da74 fix(slack): support native slack approvals on enterprise grid (#120942)
* fix(slack): support Grid native approvals

* test(slack): tighten Grid approval validation

* fix(slack): pass Grid scope to native approvals

* fix(slack): narrow Grid approval event scope

* refactor(slack): centralize optional approval scope

* refactor(slack): reuse approval target formatter

* refactor(slack): use generic target formatter

* refactor(slack): centralize explicit target formatting

---------

Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
2026-08-10 03:42:59 +00:00
ClawSweeper eab26ec439 fix(microsoft-foundry): write canonical image model config (#121370)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-09 20:40:11 -07:00
Peter Steinberger 914f73ac99 docs: replace retired config keys with canonical schema keys (#121330) 2026-08-09 20:30:43 -07:00
Peter Steinberger 6c1879e5e7 fix(scripts): recognize relocated subagent-registry lifecycle seam in audit (#121363) 2026-08-09 20:22:20 -07:00
Vyctor H. Brzezowski 0eeb1d80c3 fix(ui): resolve undefined Control UI font tokens (#121320)
Control UI declares its typography tokens once, in ui/src/styles/base.css:
--mono and --font-body. Fifteen rules asked for --font-mono / --font-sans
instead, names that only exist in other documents (canvas widget host,
provider OAuth page, MCP Apps spec keys). Those references are invalid at
computed-value time, so the declarations were dropped: nine had no fallback
and silently inherited the body font, and the four `font:` shorthand sites
lost their size, weight, and line height along with the family.

Point every reference at the canonical token and drop the now-dead generic
fallbacks so ui/src has one spelling per font token.

ui/src/styles/base-theme-tokens.node.test.ts already guards this bug class
for color tokens (#113726, #113776) but never listed the font aliases; add
them so a re-introduction fails the existing lane instead of shipping.
2026-08-10 00:18:51 -03:00
Peter Steinberger 578e92d333 fix(sessions): single patches no longer scan the whole store (#121349)
* perf(sessions): avoid full-store single patches

Single-session non-label patches no longer materialize the whole session store. Label uniqueness remains store-wide, and stale aliases created while queued are still rejected.

* fix(build): refresh plugin SDK API baseline

Current main's generated manifest lagged merged Plugin SDK surface changes; canonical refresh restores the baseline check.
2026-08-09 20:16:15 -07:00
Peter Steinberger 1d690762a8 fix(control-ui): restore authenticated assistant profile avatars (#114503)
* fix(control-ui): authenticate assistant avatars

* fix(control-ui): use public sidebar context seam

* fix(ui): keep avatar timeout abort compact

* fix(ui): release inactive avatar routes

* test(ui): flush deferred avatar cleanup
2026-08-09 20:09:27 -07:00
Peter Steinberger 79eb5bde43 refactor(agents): consolidate session and tool attempt steps (#121344)
* refactor(agents): consolidate session-phase attempt steps

* refactor(agents): consolidate tool-phase attempt steps

* refactor(agents): repoint consolidated tool imports

* refactor(agents): remove absorbed session and tool steps

* test(agents): preserve merged session mock exports

* refactor(agents): preserve attempt phase leaf contracts
2026-08-09 20:06:22 -07:00
Peter Steinberger 8430fc0e3b refactor(agents): move spawn family into subagents/spawn (#121350)
* refactor(agents): move spawn family into subagents/spawn

* refactor(agents): keep spawn imports within lint budget
2026-08-09 19:51:29 -07:00
Peter Steinberger 5d191c3984 fix(agents): exclude private shell output from context compaction (#121147)
* fix(agents): exclude private shell output from context compaction

## What Problem This Solves
Shell executions explicitly excluded from model context could still contribute their private output to session replay, token estimates, compaction boundaries, or branch summaries.

## Why This Change Was Made
The session projection owner now omits context-excluded shell messages, while compaction assigns those messages zero tokens and prevents private persisted entries from becoming retained-history cut boundaries.

## User Impact
Private shell output remains durably recorded for its intended owner without leaking into model-visible conversation context or wasting compaction budget; legitimate retained context remains intact.

## Context
Actual production code executed in an isolated VM reduced more than 20,000 characters of private output to zero model-visible characters while preserving eligible context. New owner and sibling regressions cover replay, compaction, branch summaries, and token accounting. Existing oxfmt formatting and scoped whitespace checks passed.

* test(agents): cover private Codex history projection
2026-08-09 19:50:50 -07:00
Peter Steinberger 188a248449 fix(test): restore root-matrix unit-fast cleanup (#121356) 2026-08-09 19:44:44 -07:00
Peter Steinberger f44c5e2e5e fix(plugins): surface manifest-only bundled capabilities (#121354)
Use a manifest-first inventory with independent coverage for manifest-only bundled capabilities.

Retire the undocumented thread-ownership plugin while Doctor removes stale references.

Document Talk voice and persist only provider-scoped voice selection.

Closes #121353
2026-08-09 19:43:49 -07:00
Peter Steinberger ca6a379745 refactor(core): delete duplicate account-id, sleep, and config wrappers (#121312)
* refactor(core): delete duplicate account-id/sleep/config wrappers

* chore(plugin-sdk): refresh API contract baseline

* chore(plugin-sdk): regenerate API baseline after rebase

* chore(lint): ratchet export-name-collision baseline after wrapper deletions
2026-08-09 19:41:30 -07:00
Peter Steinberger fe6ce17033 chore: expose repo skills to Claude Code via .claude/skills symlink
Symlink .claude/skills -> ../.agents/skills so Claude Code sessions can load
repo skills (test-audit authoring gate, openclaw-testing, pr-maintainer)
that were previously Codex-only.
2026-08-09 19:38:16 -07:00
Peter Steinberger 88fc335323 fix(ci): support frozen script entrypoints (#121208)
* fix(ci): support frozen script entrypoints

* fix(ci): route frozen plugin tests through package script

* fix(release): support compiled candidate test helpers

* fix(release): support compiled upgrade helpers

* fix(release): mount trusted upgrade runtime

* fix(release): preserve trusted tsx resolution
2026-08-10 10:31:21 +08:00
Peter Steinberger da0fad6718 fix(usage): expand Windows footer template paths (#121303) 2026-08-09 19:29:10 -07:00
Peter Steinberger a8714eea9a docs(agents): add test-audit authoring gate and net-neutral bug-fix doctrine
- 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.
2026-08-09 19:24:36 -07:00
Peter Steinberger d9bed81982 perf(sessions): scope entry cache revalidation (#121342) 2026-08-09 19:17:38 -07:00
Peter Steinberger 587eaf42a1 fix(agents): pair reset tool results within retained session history (#121146)
* 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
2026-08-09 19:14:55 -07:00
Vincent Koc 4ee008a026 fix(qa): reuse one immutable Docker candidate (#121253)
Punchcard-Session: amber-workshop-workshop-36

Co-authored-by: Dallin Romney <6581799+RomneyDa@users.noreply.github.com>
2026-08-10 10:14:24 +08:00
Peter Steinberger 3b641a145e fix: preserve GPT-5 personality through doctor migration (#121346)
Operators who disabled the GPT-5 friendly interaction style now keep that preference after openclaw doctor --fix. Existing OpenAI plugin personality config remains authoritative.
2026-08-09 19:14:08 -07:00
Peter Steinberger 0ce757027a fix(ui): restore Desktop panel launchers (#121322)
* fix(ui): restore Desktop panel launchers

* perf(ui): keep Desktop launchers within startup budget
2026-08-09 19:08:54 -07:00
Peter Steinberger e61ba9c1ea fix(scripts): fall back to local check:changed lanes on full Crabbox provider outage (#121323)
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.
2026-08-09 19:06:01 -07:00
Peter Steinberger 50026f1031 refactor(core): canonicalize record guards on normalization-core (#121331)
* refactor(core): canonicalize record guards on normalization-core

* chore(plugin-sdk): refresh API baseline
2026-08-09 19:05:13 -07:00
Peter Steinberger 3d5f916523 fix(protocol): align fallback reason schemas (#121334)
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.
2026-08-09 19:02:23 -07:00
Sarah Fortune 732108d973 feat(slack): add workspace routing for Enterprise Grid actions and events (#121014)
* fix(slack): preserve team scope for deferred actions

* refactor(slack): use typed Bolt team context

* refactor(slack): preserve deferred action IDs

* refactor(slack): treat team IDs as opaque

* refactor(slack): keep deferred action diff focused

* fix(slack): enable scoped enterprise interactions

* fix(slack): keep event scope at listener boundary

* test(slack): model Bolt enterprise interaction context

* refactor(slack): normalize listener team context

* refactor(slack): pass modal event scope directly

* test(slack): preserve interaction harness argument types

* refactor(slack): pass shortcut event scope directly

* refactor(slack): pass action event scope directly

* fix(slack): scope enterprise slash commands

* test(slack): disambiguate slash harness scope

* fix(slack): type slash block suggestions

* fix(slack): preserve option text literal

* fix(slack): keep scope helpers private

* fix(slack): fall back from slash response URLs

* fix(slack): clarify Web API post message call

* fix(slack): scope post message lint suppression

* fix(slack): preserve event scope export after rebase

* fix(slack): preserve team-bound modal session routing

* fix(slack): retain modal direct-message routing

* fix(slack): preserve modal delivery compatibility

* docs(slack): mark enterprise tool actions supported

* docs(slack): align enterprise support with runtime

* test(slack): align enterprise interaction registration

* fix(slack): support Grid channel create and rename events

---------

Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
2026-08-10 02:02:15 +00:00
Peter Steinberger f805ad0354 refactor(extensions): remove unused compatibility exports (#121338) 2026-08-09 19:01:38 -07:00
Peter Steinberger 64695e5024 chore: detect export name collisions (#121300)
* chore(scripts): add export-name-collision check with debt baseline

* chore(scripts): allowlist per-module test-hook export idiom

* chore(scripts): recognize const forwarders, harness files, and JS sources in collision check
2026-08-09 18:58:28 -07:00
Peter Steinberger c3a0d3e58a test(android): enforce shared talk config contract (#121333) 2026-08-09 18:55:04 -07:00
Kevin Lin 96c5aa86f2 fix(codex): keep Slack turns running when a plugin is disabled (#120312)
* fix(codex): isolate plugin activation failures

* fix(codex): report rejected plugin installs

* refactor(codex): isolate app-server RPC errors

* fix(codex): classify terminal plugin install rejections
2026-08-09 18:54:28 -07:00
Peter Steinberger f4e62523af fix(update): preserve upstream after pinned dev updates (#121328) 2026-08-09 18:50:12 -07:00
Peter Steinberger 2f97e8c9eb fix(gateway): deliver scoped global session events (#121166)
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.
2026-08-09 18:50:08 -07:00
Peter Steinberger 620fcd0e27 refactor(plugins): make manifests own config ui hints (#121329) 2026-08-09 18:48:49 -07:00
Peter Steinberger a6c410ef51 fix(agents): preserve retries after failed rate-limit rotation (#121325) 2026-08-09 18:46:06 -07:00
Peter Steinberger 5207c4765d feat(ui): float task-suggestion cards top-right with copy-prompt action (#121259)
* 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.
2026-08-09 18:45:47 -07:00
Peter Steinberger ba5895a976 test(discord): remove duplicate inbound context contract (#121318) 2026-08-09 18:28:14 -07:00
Peter Steinberger b05a308351 refactor(agents): consolidate prompt and stream attempt steps (#121305)
* refactor(agents): consolidate prompt-phase attempt steps

* refactor(agents): move stream transport into settlement module

* refactor(agents): remove absorbed stream transport step

* test(agents): preserve merged prompt mock exports
2026-08-09 18:25:43 -07:00
Vyctor H. Brzezowski 32ced3053d fix(ui): scope the Control UI cursor convention to app-like display modes (#121258)
* 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.
2026-08-09 22:23:00 -03:00
Peter Steinberger 9066ba948a fix(gateway): accept tls_certificate in worker-live fallback reason schema (#121285)
* fix(gateway): accept tls_certificate in worker-live fallback reason schema

* chore(gateway): refresh plugin SDK API baseline

* test(gateway): move worker-live failover conformance guard
2026-08-09 18:21:29 -07:00
Peter Steinberger 1c95854163 refactor(media): fold per-kind alias shells into per-concern modules (#121302)
* refactor(media): fold per-kind alias shells into per-concern modules

* test(ci): retarget media test inventories after shell fold
2026-08-09 18:19:38 -07:00
Vito Cappello 7d129279a4 fix(agents): prevent requester settle while child is still running (#120601)
* 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>
2026-08-09 18:19:22 -07:00
Peter Steinberger a3b4c0aa71 fix(acp): preserve source runtime ownership for bound turns (#110261) 2026-08-09 18:12:26 -07:00
Peter Steinberger 3c09da59f6 test(sessions): remove assertion-free history kick probe (#121310) 2026-08-09 18:08:16 -07:00