Commit Graph

79491 Commits

Author SHA1 Message Date
Peter Steinberger bb9b22ddae fix(ci): manual full CI fails in temporary workflow fixtures (#124077)
* test(ci): resolve fixture loaders from workspace

* test(ci): preserve protocol fixture dependency
2026-08-15 00:55:32 -07:00
Peter Lee 107f03d177 fix(agents): publish resolved model identity in agents_list output (#123044)
agents_list exposed the raw configured primary (routing alias) as the
model field while agentRuntime was derived from the resolved model,
giving agents two contradictory identities. Publish the resolved
provider/model from resolveDefaultModelForAgent instead, matching the
gateway agents.list fix (#122907).
2026-08-15 10:52:47 +03:00
Peter Steinberger 34efe370b2 test(core): trim duplicate strict-subset assertions (#124090) 2026-08-15 00:52:34 -07:00
Peter Steinberger d1f8c339b1 fix(onboard): provision workspace before config commit (#124092) 2026-08-15 00:48:19 -07:00
Peter Steinberger d74a69ec3d fix(gateway): publish replay-observed approval expiry (#124087) 2026-08-15 00:45:47 -07:00
Peter Steinberger 52adbf4c60 fix(acp): cancel pending prompts when the bridge shuts down (AI-assisted) (#124068)
* fix(acp): cancel pending prompts on shutdown

ACP shutdown now aborts accepted Gateway runs and releases bridge session state rather than leaving prompts pending.

* fix(acp): preserve injected store ownership

Keep caller-provided ACP session stores generic while disposing only the concrete store created by the agent.
2026-08-15 00:45:42 -07:00
Peter Steinberger 49e1ea2c9f fix(cli): redact machine-readable CLI error payloads (#124075) 2026-08-15 00:44:18 -07:00
Peter Steinberger f2c721b0ac fix(test): unshadow capture-helper catch bindings
check-lint-core-4 (run 31872054461) flagged no-shadow: the failure
diagnostics refactor in c59ef0b40c named its parameter 'error' while
two inner catches reused the name.
2026-08-15 00:35:54 -07:00
Peter Steinberger 9e911d5601 test(cua): remove stale provider parity fixtures (#124066) 2026-08-15 00:28:55 -07:00
Peter Steinberger d2be00e171 feat(ui): persistent emoji session icons in the sidebar (#124034)
* feat(gateway): persist emoji session icons

* feat(ui): add persistent session icon menu

* docs: explain persistent session icons

* docs: list Set icon in the session context menu enumeration

* test(gateway): canonicalize group defaults workspace path

* fix(ci): sync session icon protocol coverage

* fix(sessions): enforce RGI emoji sequences for session icons

ClawSweeper P2: single non-emoji graphemes like 漢 passed the segmenter-based predicate. Anchored \p{RGI_Emoji} admits exactly one interchange emoji sequence and deletes the length cap and ASCII carve-out.

* fix(sessions): compile RGI emoji validation
2026-08-15 00:15:55 -07:00
Peter Steinberger 079bb34196 feat(cua-computer): recording family with host-owned resource handles (#124035)
* feat(cua-computer): add recording resource handles

* test(agents): split computer tool coverage
2026-08-15 00:14:13 -07:00
Peter Steinberger 6d9ea63a87 docs: correct computer use inventory counts (#124074) 2026-08-15 00:13:16 -07:00
Peter Steinberger c59ef0b40c fix(test): serve deep-link assets like the Gateway in the Control UI e2e preview server
Root cause of the checks-ui-e2e boot-stall flake (run 31867505277): the
built index.html references modules relatively (./assets/*), and the real
Gateway resolves /assets/ at any path depth (src/gateway/control-ui.ts),
but the e2e preview server let Vite's SPA fallback answer
/chat/assets/index-*.js with index.html as text/html. The browser rejects
that module silently (console-only, no pageerror), so a document reloaded
on a deep link like /chat/research never boots. Under CPU load the
harness's replaceState("/")+reload pair raced the router's redirect and
reloaded on the deep link, producing the all-null 30s poll.

- Preview server now mirrors the Gateway's depth-insensitive /assets/
  resolution; the racy replaceState canonicalization hack is deleted.
- Deterministic regression test boots a document directly on
  /chat/research; mutation-proven (fails with the middleware disabled).
- Failure diagnostics generalized: boot waits capture screenshot, script/
  resource evidence, pageErrors, and a navigation-traced event ring.

Proof: Testbox tbx_01m022feapn38ypws3mb2b9jhv saturated loops — pre-fix
2/10 failed with the exact CI signature; post-fix 0/14 at the same pace.
2026-08-15 00:12:14 -07:00
Peter Steinberger 28f10c00b4 fix(codex): keep yolo approvals disabled (#124069)
Keep routine Codex commands from pausing for approval in default and team YOLO sessions. The default exec policy omitted its full mode, so a generic tool hook could promote approvalPolicy from never to untrusted.
2026-08-14 23:57:49 -07:00
Peter Steinberger 056184bccc fix(browser): preserve closed tab ownership (#124064) 2026-08-14 23:55:07 -07:00
Peter Steinberger 05028da50d fix(ui): refresh model config after reconnect (#124065) 2026-08-14 23:54:58 -07:00
Peter Steinberger 7bb3909e4b fix(workers): clean stale bundle install staging (#124057)
Serialize node worker installs per Gateway namespace so a later bundle hash reclaims interrupted staging from older hashes instead of leaking it indefinitely.
2026-08-14 23:47:42 -07:00
Patrick Erichsen ab4557d22c fix(ui): remove question expiry timer (#124063) 2026-08-15 06:42:05 +00:00
Peter Steinberger f6ed40d649 docs(agents): fact-check, disambiguate, and further slim root AGENTS.md (#124053)
* docs(agents): fact-check, disambiguate, and further slim root AGENTS.md

Second cleanup pass over root AGENTS.md driven by three audit lanes
(fact-check vs repo, confusion/contradiction hunt, cut candidates):

- Fact fixes: delete the @buape/carbon pin rule (dependency no longer exists
  in any manifest or pnpm-lock.yaml); fix the reply-format example to a real
  file (extensions/telegram/src/bot-access.ts).
- Confusion fixes: define checkout classes once in Commands and merge the
  three conflicting test/check bullets onto them; state that the mock-gateway
  harness verdict satisfies channel-visible proof as an explicit exception to
  mandatory UI screenshots; complete the Map scoped-guide list (src/tui, test)
  and note deeper subtree guides; inline the dangling 'Start-section evidence
  bar' reference; gate issue-closing and public-comment posting on explicit
  authority; scope the NO_REPLY rule to ClawSweeper hook sessions; clarify
  auto-provisioning vs Architecture's compat-fallback deletion rules.
- Cuts/moves: scripts/pr gotchas, throttle-lock recovery, non-main merge
  procedure, media-upload mechanics, and merge-ref-race recognition into
  $openclaw-pr-maintainer; QA private build flag into $openclaw-qa-testing;
  release-branch CI dispatch refs and release-ci-summary limits into
  $release-openclaw-ci; Vitest ENOTEMPTY race into $openclaw-testing;
  WebVNC screenshot etiquette into $crabbox; delete bullets duplicated by
  those skills (prompt snapshots, QA YAML) and the obsolete rebrand-doctor
  bullet; compress the preflight, Codex gate, SQLite-additive, ClawSweeper,
  and Execution Identity wording without dropping any invariant.

* docs(agents): exempt extended-stable canonical dispatch from the target_context_ref rule
2026-08-14 23:40:48 -07:00
Patrick Erichsen f6359140f1 fix(ui): show skill titles in chat reference picker (#124017)
* fix(ui): use skill names for chat references

* fix(ui): show skill titles in reference picker
2026-08-14 23:39:02 -07:00
Peter Steinberger a8f1a0d345 test(computer-use): live end-to-end gate for both macOS providers (#123991)
* fix(computer-use): preserve semantic click observations

* fix(cua-computer): isolate desktop and window sessions

* fix(cua-computer): route cursor reads through desktop scope

* test(computer-use): add isolated macOS live proof rig

* style(cua-computer): format driver sessions

* fix(cua-computer): forward lazy desktop tools

* fix(computer-use): narrow live proof artifact path

* test(computer-use): split schema contract coverage

* refactor(cua-computer): unify session start state

* build(computer-use): register live proof entrypoint

* style(computer-use): satisfy full lint contract

* fix(computer-use): harden live proof authority

* fix(cua-computer): keep window authority immutable

* fix(computer-use): close partial sessions safely
2026-08-14 23:37:53 -07:00
Peter Steinberger 2adbdd75c6 fix(gateway): preserve managed media lifecycle outcomes (#124048) 2026-08-14 23:35:23 -07:00
Patrick Erichsen 1e91253f1e fix(ui): slow active-run spinner (#124058) 2026-08-14 23:29:38 -07:00
Peter Steinberger 45ad442497 fix(ui): surface failed Canvas dashboard pins (#124044) 2026-08-14 23:28:29 -07:00
Peter Steinberger 3f6bf166b6 fix(memory): preserve provider on cancelled search (#124051) 2026-08-14 23:28:16 -07:00
Peter Steinberger 9050ff0e9e test(acp): remove cleanup-only session seam (#124043)
* test(acp): remove cleanup-only session seam

* test(infra): stabilize routing and PID readiness

* test(gateway): synchronize post-rejection frame proof
2026-08-14 23:26:33 -07:00
Ayaan Zaidi 2e806ef0e2 fix(codex): keep the real answer when a trailing coda follows (#123993)
* fix(codex): keep prior finals when a coda follows without tool work

Live persist last-won a single assistant slot, so a trailing final_answer
replaced the real summary. Keep explicit finals after the last native tool;
phase-less coordination text stays last-wins.

* fix(codex): record the native-work barrier from item notifications

turn/completed.items is a last_agent_message Summary, so result-time
tool scans cannot see intervening work. Invalidate persistable finals
when native tools arrive, drop trailing silent tokens, and let a later
unphased message replace earlier finals.

* fix(codex): make the persistable-text barrier once-per-handoff

Delayed native completions must not move the barrier past an answer that
arrived while that tool was already active. Dynamic tool calls are the
same handoff. If no audible text exists after the barrier, recover the
last persistable answer instead of dropping it.

* fix(codex): keep a post-handoff silent final authoritative

A tool after an audible final starts a new answer segment. If that
segment is NO_REPLY, do not revive the pre-tool text. Recover a prior
answer only when the post-handoff segment is empty.

* fix(codex): classify silent finals with the delivery payload predicate

Token-only matching missed JSON and reasoning-wrapped NO_REPLY
payloads, so a trailing control envelope could join into the visible
answer. Use the shared payload-level predicate.

* fix(codex): honor unphased replacement and sleep handoffs

A later unphased item must invalidate older finals even when a later
final skips it, and sleep is a native answer barrier.
2026-08-15 11:36:33 +05:30
Peter Steinberger 8b200f3523 fix(ui): keep the chat transcript anchored while the pane resizes (#124013)
* fix(ui): keep the chat transcript anchored while the pane resizes

The width-change path wiped the virtualizer's entire item-size cache
(instance.measure()), collapsing every offscreen row to the 120px estimate
with no scroll compensation: the reader teleported mid-transcript and the
trickle of remeasure corrections made text visibly jump for several frames
on every pane or window resize.

Keep the stale offscreen sizes as estimates instead. The existing
synchronous resizeItem pass plus TanStack's per-row ResizeObserver re-seed
connected rows with fold-based scroll compensation, so the anchor row holds
still; offscreen rows correct lazily as they connect. End-pinned transcripts
keep following the tail via the existing height-change scrollToEnd path.

Regression e2e: mid-transcript anchor stays within 60px across
1280->1000->820->1280 resizes (pre-fix: anchor scrolled out of the viewport
entirely and scrollTop drifted by 250px+). Wipe introduced in #115059,
refined by #117687/#123713 without addressing anchoring.

* test(infra): deflake ephemeral-port rebind proof under runner contention

The bind->release->rebind cycle races foreign processes on shared CI
runners: a stolen port between release and rebind fails the assertion
(EADDRINUSE, seen on checks-node-compact-large-17). Retry the whole cycle
on a fresh ephemeral port, bounded at 5 attempts; a genuine release
regression still fails every attempt because the collision is with our
own lingering listener.

* test: prove port release on the allocated port; add end-pin resize proof

Address ClawSweeper review on #124013:
- ports-probe: replace the fresh-port retry with a connect probe against the
  same allocated port. A lingering listener accepts the probe; a released
  port refuses it. Unlike a rebind, the probe does not collide with foreign
  outbound sockets that transiently occupy the port on busy runners, so the
  release contract stays tied to one port with no retry at all.
- chat-resize-anchor e2e: add a width-only end-pinned case proving the
  virtualizer's wasAtEnd compensation keeps the transcript within 2px of
  the end across 1280->1000->820->1280 resizes.

* test(ui): widen resize-anchor drift bound for Linux font metrics

The fold-spanning anchor row re-wraps by a renderer-dependent amount
(42px macOS, 63px Linux CI at 820px). 120px keeps a wide margin below
the pre-fix failure mode (anchor out of viewport, 250px+ drift).

* test(tooling): register manager-session-update-race in memory helper routing

#124024 added the memory-core test on main without updating the
cross-lane routing expectation in test-projects.test.ts, breaking the
core-tooling shard on every merge ref that includes it.
2026-08-14 23:00:13 -07:00
Jason (Json) a02ed2cfda fix(plugin-sdk): installed llama providers fail to load after upgrade (#124041)
* fix(plugin-sdk): let installed llama providers load after upgrade

* test(tooling): include new memory race importer
2026-08-14 23:57:24 -06:00
Peter Steinberger f24bd8a2a2 fix(ui): use session-key equivalence for active-row lookups in model/thinking/fast-mode paths (#124020)
Six sites strict-compared row.key === sessionKey while the sibling locked
check already used areUiSessionKeysEquivalent (#104045 upgraded only the
model path). In alias/transition windows (pre-hello legacy 'main' vs
canonical agent:main:main) the optimistic thinking/fast-mode row patch
found no row — the click produced no immediate visible change — and the
display resolvers missed the active row, falling back to agent defaults.
All lookups now go through the equivalence helper the rest of the flow
uses.
2026-08-14 22:39:54 -07:00
Peter Steinberger ab8d7dbb21 fix(gateway): report plugin HTTP dispatch failures as 500 (#124033)
* fix(gateway): preserve plugin HTTP failure ownership

Plugin HTTP dispatch failures now reach the Gateway's bounded 500 response instead of falling through as an unclaimed 404 route.

* test(gateway): assert plugin HTTP failure log

* refactor(gateway): remove dead HTTP stage labels
2026-08-14 22:39:32 -07:00
Peter Steinberger 49e783da74 perf(test): narrow Tlon monitor SDK mocks (#124036) 2026-08-14 22:37:02 -07:00
Peter Steinberger 83319bad60 docs(agents): dedupe root AGENTS.md and move workflow detail into owning skills (#124027)
* docs(agents): dedupe root AGENTS.md and move workflow detail into owning skills

Root AGENTS.md loads into every session; ~9.5KB of it duplicated content
already owned by skills (crabbox, openclaw-testing, release-openclaw-*,
openclaw-pr-maintainer, openclaw-changelog-update) or restated the same
invariant in multiple sections. Skills absorb the root-only operational
details first (Testbox/Crabbox mechanics, backport default target, fork-code
landing variant), then root keeps hard policy and routing only.

Also fixes skill drift found during the audit: positional testbox status id,
missing remote-unavailable local-fallback policy, delegated-flag reject list,
and aligns the early performance dispatch fail_on_regression flag with the
Full Release Validation profile gate (true stable / false beta).

* docs(agents): derive fail_on_regression from release profile in dispatch example
2026-08-14 22:34:27 -07:00
Peter Steinberger 3f7c8522b7 fix(discord): stop stale voice playback after leave (#124030)
Discard TTS that settles after a Discord voice session stops, release queued streams, and remove file-backed playback artifacts after use.
2026-08-14 22:31:11 -07:00
Peter Steinberger f8fcc7f99b test(ui): remove sidebar capture harness (#124031) 2026-08-14 22:29:48 -07:00
Peter Steinberger 2e90d67312 test(cua): trim generic browser transport replays (#124011) 2026-08-14 22:24:41 -07:00
Jesse Merhi edb5adfbf5 Start new sessions with folder group defaults (#123276)
* feat(ui): add folder group session defaults

* fix(ci): align folder group contracts

* fix(protocol): refresh Android gateway methods

* fix(ui): reuse folder picker for group defaults

* fix(ui): harden session group defaults

* test(ui): align group defaults with current main

* test(ui): keep group catalog defaults path-free

* fix(ui): close folder group CI gaps

* fix(ui): satisfy folder group CI contracts

* fix(session-groups): enforce defaults safety

* test(gateway): keep group defaults in workspace

* fix(session-groups): enforce defaults participation

* fix(session-groups): close review authorization races

* fix(session-groups): canonicalize defaults authorization

---------

Co-authored-by: Jesse Merhi <jesse-merhi@users.noreply.github.com>
Co-authored-by: Jesse Merhi <openclaw@users.noreply.github.com>
2026-08-15 15:24:13 +10:00
Peter Steinberger 2ee5c2f6ca fix(memory): queue transcript updates during active sync (#124024) 2026-08-14 22:20:53 -07:00
Bek 5a5bf4d524 fix(codex): preserve native child continuation on yield (#124004) 2026-08-15 01:13:09 -04:00
Peter Steinberger af76f494cc test(ui): give the run-inspector bottom-bound assertion its real sub-pixel tolerance
Broke the main gate on run 31865993941 (checks-ui-e2e 2/12):
expected 609.81 <= 609.21. The preceding scroll poll tolerates a <=1px
remainder because scrollHeight/clientHeight are integer-rounded, while
measureWithinAncestor compares fractional getBoundingClientRect values,
so the true bound is 2px, not 1.
2026-08-14 22:11:17 -07:00
Peter Steinberger 1320a0bff9 feat(lint): reject widen-then-assert type laundering (#124003)
* feat(lint): add no-widen-then-assert guard

* refactor: preserve typed boundary evidence

* refactor(types): remove redundant unknown aliases

* fix(agent): preserve replay sanitizer fallback

* fix(lint): close widen-then-assert nested-chain and const-alias bypasses
2026-08-14 22:10:19 -07:00
Peter Steinberger 6a78332c4c fix(ui): dedupe chat header owner presence (#124006) 2026-08-14 22:03:27 -07:00
Peter Steinberger c7090706d4 fix(ui,gateway): refresh the agents-page model catalog on picker open and give catalog errors a next step (#124019)
The agents-page model catalog was cached per agent for the whole
connection: availability facts (provider keys added/removed, new models)
went stale with no refresh path except a full reconnect, while the chat
composer's sibling picker refreshes on open. Opening the overview picker
now re-reads through the same ensureModelCatalog owner with a refresh
bypass of the per-agent cache.

sessions.patch's 'model catalog unavailable' error told the operator
nothing actionable; it now states the catalog is still loading and to
retry — the failure text names the next step per doctrine.
2026-08-14 22:00:55 -07:00
Peter Steinberger 19ae7f2110 perf(ci): keep hybrid Windows on one Blacksmith lane to dodge the 2-runner queue
Measured on run 31865243804: the 3-part split on
blacksmith-8vcpu-windows-2025 got exactly 2 runners; part 2 queued 211s
and only started when part 1 finished, pushing the wall to 6:45 despite
133-163s job bodies (vs 342s hosted). The runner class admits ~2
concurrent jobs, so any profile that can land on Blacksmith now uses the
single lane; the 3-part split stays for guaranteed-hosted executions
(github mode and dispatches, whose runner expression forces hosted in
every mode). A hybrid retry reruns the single lane hosted - slower but
bounded, and Windows-scoped retries are rare.
2026-08-14 22:00:25 -07:00
Peter Steinberger af76425d87 fix(channels): preserve legacy ingress failure settlement (#124016) 2026-08-14 21:59:16 -07:00
Peter Steinberger 7ac49e280e refactor(ui): delete the permanently no-op onModelChanged seam (#124009)
state.onModelChanged has been () => undefined since the original Control
UI refactor (65e12328aa) and was never overridden; three call sites
awaited a decoy. Effective-tools previews key their requests on the model
override, so the post-switch refresh only needs a re-render, and the
model-switch reconcile already awaits the canonical session-list refresh.
Tests that used the seam as a deferral hook now hold the list refresh
open instead — the barrier the production code actually awaits.
2026-08-14 21:58:42 -07:00
Peter Steinberger 124847928d fix(cli): name the agent escapes each command supports (#124018)
* fix(cli): name supported agent selection escapes

* refactor(cli): keep selection context compact

* fix(cli): preserve caught selection errors
2026-08-14 21:58:11 -07:00
Peter Steinberger 6e5bf3ec55 fix(doctor): stop false failures on multi-agent profiles (#124010)
* fix(doctor): resolve multi-agent health owners

* fix(doctor): keep bare json exit advisory
2026-08-14 21:45:55 -07:00
Peter Steinberger f0d277277b test(perf): assert live duplicate tombstones (#124012) 2026-08-14 21:45:48 -07:00
Peter Steinberger f6f0fd9e1e fix(ui): retire the local model override once the Gateway confirms the patch (#124005)
* fix(ui): retire the local model override once the Gateway confirms the patch

settleModelOverride re-asserted the requested model into the shared
override map after every successful patch, and the reader prefers the map
over the server row unconditionally — so any external model change
(second operator window, channel /model, fallback rotation persisted by
the Gateway) never reached this window's picker or its effective-tools
key for the rest of the connection. The refreshed row already carries the
confirmed selection; retire the entry instead of shadowing the recorded
fact. deferListRefresh callers keep the published value (their refresh
has not run), rollbacks and newer-claim transfers are untouched.

* test(ui): split model-override lifecycle coverage into a focused file (max-lines)
2026-08-14 21:39:19 -07:00