Commit Graph

71273 Commits

Author SHA1 Message Date
Josh Avant 3acc168c4f fix(cron): persist explicit scheduled tool authority (#112483)
* fix(cron): persist explicit scheduled tool authority

* test(cron): cover explicit scheduled authority

* fix(cron): preserve legacy authority on routine edits

* test(cron): add explicit authority e2e matrix

* test(cron): harden explicit authority live proof
2026-07-22 02:28:49 -05:00
Dallin Romney 132d91e427 refactor(qa): make taxonomy coverage ids unique (#110280) 2026-07-22 16:28:44 +09:00
Vito Cappello 4ab686220f fix(memory): recover from same-file legacy index divergence (#110216)
* fix(memory): keep canonical rows when same-file legacy memory tables diverge

* fix(memory): keep canonical-owned sources' chunk sets coherent during legacy import

* fix(memory): import legacy chunks when canonical source has no chunks

The same-file legacy migration excluded a legacy chunk from import whenever the
canonical index already had a source row for its (path, source). That stranded a
file whose canonical source was registered but had no chunks yet (indexing
interrupted before chunks were written, or embedding pending/failed): the legacy
chunks were its only searchable content, and the matching source hash stops sync
from re-indexing, so the file went silently unsearchable.

Re-key the chunk-coherence exclusion on canonical chunk ownership instead:
snapshot the (path, source) pairs that already have canonical chunks before the
import and skip legacy chunks only for those. A source with a canonical row but
no chunks now imports its legacy chunks. The snapshot is taken pre-insert because
the exclusion predicate reads the chunks table the import writes to.

Add regressions: legacy chunks import for a chunk-less canonical source while a
chunk-owning source still drops its stale legacy chunk; and restore abort
coverage for the meta and chunks copy assertions (previously only files was
exercised).

* fix(memory): harden same-file legacy conflict recovery

* fix(memory): rebuild ambiguous partial legacy sources

* fix(memory): reconcile migrated derived indexes

* fix(memory): close migrated index ownership gaps

* test(memory): align migration expectations

* test(tooling): match routed test order

* test(memory): exercise vector reload cleanup

* test(memory): prove real vector reload cleanup

* fix(memory): make migrated indexes converge

---------

Co-authored-by: Serhii Leniv <leniv.tech@gmail.com>
Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-22 00:27:01 -07:00
Peter Steinberger 3c4a1ec905 refactor(agents): move CLI backend adapters from config DSL to registerCliBackend plugins (review request) (#112539)
* refactor(agents): move CLI backend adapters into plugins

* test(agents): register CLI backend fixtures through plugins
2026-07-22 00:25:29 -07:00
Peter Steinberger b02d3e4707 feat(scripts): reference update script for source-checkout gateway servers (#112557)
* feat(scripts): reference update script for source-checkout gateway servers

Teams running a gateway from a git checkout kept re-deriving the same
update ritual by hand: restore the tracked bundle pnpm build rewrites,
fail closed on real local changes, fast-forward main or rebase a local
server branch, install deps, build clean (incremental builds have
shipped stale hashed chunks), restart the service. update-gateway.sh
encodes that as the documented reference; simple installs keep using
openclaw update --channel dev.

* fix(scripts): harden update-gateway guards and refresh docs map

Review findings: never run over a pre-existing rebase/merge/cherry-pick
(the abort path could discard operator progress), and treat untracked
files honestly — fail closed only where the clean build would delete
them, warn-list elsewhere. Regenerate docs_map for the new updating.md
section.

* fix(scripts): pipefail-safe warnings and honest disposable-dir policy

Review findings: head-truncating a long warning list through a pipe
dies under pipefail (SIGPIPE) in the warning path, so truncate via
here-strings; the untracked-under-build-dirs guard was theater since
ignored files bypassed it — declare dist/dist-runtime/.artifacts as
wholly disposable instead and say so; note the rm targets are
symlink-safe (no trailing slashes).

* fix(scripts): order guards before mutations and refuse symlinked build dirs

Review round: the in-progress-operation guard now precedes the bundle
restore (the script's first mutation), symlinked build dirs are refused
before the recursive clean (intermediate symlink resolution would
redirect the delete outside the checkout), and the untracked-files note
no longer overpromises — kept files can affect the build and the
message says so.

* fix(scripts): preserve merge commits when rebasing the server branch

Plain git rebase flattens merges, silently dropping merge-only conflict
resolutions from a local server branch; --rebase-merges keeps them.
2026-07-22 07:25:14 +00:00
Peter Steinberger f2a3371656 test(ui): isolate full chat-pane lifecycle tests to fix core-runtime-media-ui flake (#112566)
The core-runtime-media-ui shard runs its ui config non-isolated for speed, but the
full chat-pane lifecycle tests instantiate the pane component, which relies on
chat-thread/chat-message module-level singletons (thread-state map, confirmation
dismisser WeakMap, module-scoped document context-menu listeners) and spies on those
modules. Under the shared non-isolated graph a stateful predecessor file can leave
those modules duplicated, so the pane binds to a different instance than the test's
spy/registry -- producing order-dependent flakes: `removeEventListener`-not-called
teardown assertions or 120s session-lifecycle hangs. Reproduced deterministically on
a Linux Node 24 Testbox (MAX_WORKERS=1); isolating a single file only shifted the
failure to a sibling pane test, so the whole full-pane family shares the fragility.

Route the 7 full-pane lifecycle test files through a new isolated jsdom lane
(vitest.ui-isolated.config.ts, isolate: true) for a fresh module graph; the other
~370 ui tests stay fast and non-isolated. Registered in both shard registries
(ci-node-test-plan.mjs, vitest.test-shards.mjs) and excluded from vitest.ui.config.ts.

Verified on Testbox: the deterministic single-worker media-ui shard goes from failing
to 5182 passed / 0 failed. Test-infrastructure only; no product code changes.
2026-07-22 00:14:33 -07:00
Peter Steinberger c24a215fe4 fix: prevent announce restart recovery cascades (#112534)
* fix(agents): stop announce restart recovery cascades

Reconcile interrupted completion handoffs from existing run and transcript provenance, and keep their CLI, embedded, and Codex execution tool-free.\n\nCo-authored-by: Moeed Ahmed <moeedahmed@users.noreply.github.com>

* chore: preserve prior-art credit

Co-authored-by: Moeed Ahmed <moeedahmed@users.noreply.github.com>

* fix(agents): prefer explicit restart recovery runs

* fix(agents): revalidate announce recovery ownership

* test(agents): consolidate announce recovery cases

* fix(agents): preserve silent announce fallback

---------

Co-authored-by: Moeed Ahmed <moeedahmed@users.noreply.github.com>
2026-07-22 00:05:18 -07:00
Peter Steinberger bfb371f8d7 refactor(agents): one session-activity note pipeline for observer and narrator (#112553)
* refactor(agents): one session-activity note pipeline for observer and narrator

* refactor(agents): keep note reader helper module-local
2026-07-22 00:01:19 -07:00
Peter Steinberger 6f7388c9cc feat(ui): teach the working claw three new rare tricks (#112552)
Zen (2%) breathes through a 6s cycle with one deliberate late snip,
drummer (1%) rocks a two-beat rhythm with jaw hits on the tilts, and
peekaboo (1%) ducks down small and pops back wide open. All three stay
in place (scale/rotate/vertical only); weights rebalance from the
default and southpaw stances.
2026-07-22 00:00:25 -07:00
Peter Steinberger 3ed2a144ac fix(process): keep secret pipe errors handled (#112550) 2026-07-21 23:59:19 -07:00
Peter Steinberger 344feae7a1 fix(ui): hide presence avatar initials fallback when the image renders (#112523)
The initials fallback span inside openclaw-viewer-avatar was hidden with a
single-class selector (.viewer-avatar__fallback, 0-1-0) that the later
.viewer-avatar > span display rule (0-1-1) outranks, so image avatars rendered
the photo and the colored initials side by side in the who's-online roster,
footer facepile, and session facepiles. Bump the hiding selector to
.viewer-avatar > .viewer-avatar__fallback so it wins again; the
.is-fallback swap (0-3-0) still shows initials when the image fails to load.

Regressed in #111421.
2026-07-21 23:58:56 -07:00
Peter Steinberger 59f63ccc3b refactor: declare subagent spawn lineage explicitly so forks and dashboard chats stay spawn-capable (#112535)
* refactor(gateway): declare spawn lineage explicitly at sessions.create

Spawn depth is now a declared fact, never inferred from parentSessionKey.
sessions.create accepts an optional spawnDepth (requires parentSessionKey) that
spawn-owned creations pass; every other fresh session persists spawnDepth 0,
making operator chats and UI forks spawn-capable roots. The visible spawn tool
declares callerDepth + 1, and subagent depth recovery no longer walks
parentSessionKey, which is UI threading only.

Accepted tradeoff (documented inline): pre-upgrade visible children whose only
lineage was parentSessionKey resolve as roots; the transient population may
spawn one extra generation, still capped by maxChildrenPerAgent.

* chore(protocol): regenerate Swift gateway models for sessions.create spawnDepth
2026-07-21 23:58:19 -07:00
Peter Steinberger 5e651d5ac7 fix(channels): restore assistant context after restart (#112548)
* fix(channels): restore transcript context after restart

Merge bounded active-branch session transcript turns at the shared prepared-turn seam so message channels retain assistant replies after restart or history eviction. Migrate Telegram's one-off merge while preserving exact projection and legacy dedupe behavior.\n\nCloses #112520. Slack case reported by Joe Tam (@joetam) in #102594.

* style(channels): avoid spread in transcript mapping

* refactor(telegram): drop obsolete transcript exports
2026-07-21 23:45:01 -07:00
Peter Steinberger 01be7aa609 ci: fail build-artifacts when committed plugin bundles go stale (#112489) 2026-07-21 23:44:48 -07:00
Peter Steinberger b8ccb5dfa9 test(ui): isolate chat pane lifecycle state (#112546) 2026-07-21 23:32:53 -07:00
Peter Steinberger 1a9cb53712 refactor(media): persistence and template boundaries ride media facts (#112545)
Media-facts program PR 4: legacy Media* fields are emitted only by the
user-turn transcript writer (persisted rows byte-identical, no
migration); reads normalize into ordered facts; documented singular
template variables project per attachment with per-attachment CLI
execution. Review fix: normalized attachments carry their original fact
index so sparse aligned slots cannot shift CLI url/type projections.
2026-07-21 23:29:32 -07:00
Peter Steinberger e01f3e18a7 feat(config): tier settings as common and advanced (#112538) 2026-07-21 23:17:47 -07:00
Peter Steinberger d1d3acbd98 fix(memory-wiki): resolve keyed agent vaults (#112541)
Ensure doctor runtime tool schema checks and wiki CLI resolve agent-scoped vaults from canonical agents.entries while retaining the internal list projection fallback.
2026-07-21 23:14:22 -07:00
Peter Steinberger 8d1267dbc1 docs(agents): spell out script declaration contract and fail-loud wrapper rule (#112543)
Codex readers only reliably see the root AGENTS.md, so the .d.mts
declaration contract, the wrapper fail-loud convention, and the
stale-node_modules crash signature move from tribal knowledge into the
root file's Commands section.
2026-07-21 23:13:18 -07:00
Peter Steinberger 3cd1906e6b fix(gateway): keep dashboard sessions spawn-capable after auto-parenting to main (#112527)
Auto-parenting operator dashboard sessions to the agent main session (#110913)
collided with subagent depth recovery, which walks parentSessionKey as spawn
lineage for visible spawn children. Every WebChat dashboard session resolved to
spawn depth 1 and lost all sessions_spawn rights at the default maxSpawnDepth
of 1, breaking swarm collectors and the swarm dashboard from the web UI.

Record an explicit spawnDepth 0 on auto-parented dashboard creations so depth
recovery classifies them as roots; explicitly parented creations (visible
spawn children, forks) keep deriving depth from lineage.
2026-07-21 23:10:43 -07:00
Peter Steinberger c670fb0e27 feat(ui): show live output tokens while agents run (#112333)
* feat(ui): show live run output tokens

* fix(ui): map live usage to active runs

* test(ui): split live usage coverage

* fix(agents): scope live usage cleanup

* fix(agents): reject stale live usage events

* fix(agents): keep live usage type local

* refactor(ui): keep chat view within line budget

* fix(agents): require lifecycle for live usage

* refactor(ui): dedupe chat reply target type
2026-07-21 23:10:17 -07:00
Peter Steinberger 849ffb8a99 docs(wizard): attribute OpenClaw to the OpenClaw Foundation (#112536)
Replace the onboarding security disclaimer's "hobby project ... sharp
edges" line with a friendlier attribution to the OpenClaw Foundation (a
non-profit), matching the LICENSE copyright holder, and drop the beta
claim. Rename the now-misnamed wizard.security.beta key to
wizard.security.attribution across en/zh-CN/zh-TW and its consumer.
README intro gains the same attribution plus "learns and grows with
you".
2026-07-21 23:01:20 -07:00
Peter Steinberger 5dafb13614 chore(scripts): end failing oxlint runs with a stable status line (#112532)
* chore(scripts): end failing oxlint runs with a stable status line

A crashed run-oxlint wrapper printed only a stack trace, and a lint
invocation whose output was truncated (cmd | tail -N) read as success —
which recently let a wrapper crash (stale node_modules after a dep-adding
merge) masquerade as a clean lint. Route the CLI entry through a small
wrapper that converts crashes into exit 1 and ends every failing run
with '[oxlint] FAILED (exit N)' as the final line.

* chore(scripts): declare runOxlintCliEntry in the script declaration contract

check-guards verifies .d.mts contracts against .mjs exports and
check-test-types consumes them; the new entry export needed both the
declaration and explicit log-parameter annotations in the test.
2026-07-21 22:53:12 -07:00
Dallin Romney 3946bcc20c fix(qa): run isolated Matrix evidence partitions in parallel (#112465)
* fix(qa): parallelize isolated Matrix evidence partitions

* refactor(qa): plan adapter instance concurrency

* fix(qa): let Docker assign Matrix harness ports

* refactor(qa): use instance isolation for Matrix concurrency

* test(ci): expect maturity concurrency six

* refactor(qa): remove Matrix harness manifest
2026-07-22 14:45:52 +09:00
WhatsSkiLL feb529fd2b fix(ollama): preserve cloud model context windows (#112430)
* fix(ollama): preserve cloud model context windows

* fix(ollama): recognize cloud model source forms

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>

---------

Co-authored-by: IWhatsskill <284122573+IWhatsskill@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 22:45:03 -07:00
Patrick Erichsen a691eb7372 Revert "feat(skills): support skills-sh install references (#112517)" (#112531)
This reverts commit 7c353b7436.
2026-07-21 22:37:50 -07:00
Lu Wang 58c138374d fix(media): preserve trusted HTML provenance through outbound staging (#90579)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: wanglu241 <wanglu241@jd.com>
2026-07-21 22:36:53 -07:00
Dallin Romney 40d2af6843 docs: validate extended-stable before tagging (#112529) 2026-07-21 22:35:20 -07:00
Patrick Erichsen 7c353b7436 feat(skills): support skills-sh install references (#112517) 2026-07-21 22:33:22 -07:00
Peter Steinberger 70fd8d23c8 fix(ui): keep session narration live across chat switches (#112526)
* fix(ui): refcount session message subscriptions

* chore(release): keep changelog generation release-owned
2026-07-21 22:32:06 -07:00
Jason (Json) 1a42e005fb fix(anthropic): forward selected profiles to Claude CLI (#112458)
* fix(anthropic): forward Claude CLI auth profiles

* fix(system-agent): inject CLI auth route stores

* fix(claude-cli): pass profile credentials by descriptor

* fix(anthropic): repair selected profile CI coverage

* fix(anthropic): preserve profile owner validation

* test(system-agent): preserve selected profile fixtures

* test(system-agent): narrow selected profile fixture

* test(system-agent): resolve profile store merge

* fix(anthropic): forward profiles to node Claude runs

* fix(system-agent): reconcile profile route projection

* test(system-agent): thread profile store through projection

* fix(anthropic): make selected profile authoritative

* fix(system-agent): type auth setup failures

* fix(system-agent): type setup auth failures

* style: format Claude profile maintenance

* fix(anthropic): keep gateway credentials off nodes

* fix(anthropic): clear ambient auth for selected profiles

* fix(anthropic): secure paired-node Claude auth

* fix(node-host): type Claude fd spawn streams

* style(node-host): satisfy Claude spawn lint

* fix(process): capture exit before secret delivery

* fix(anthropic): preserve node-native Claude auth
2026-07-21 23:27:37 -06:00
Nikhil Patel 13716ad4f4 fix(cron): validate failureAlert channel at the gateway boundary (#103866)
* fix(cron): validate failureAlert channel at the gateway boundary

`--failure-alert-channel` writes patch.failureAlert.channel, a field distinct from
delivery (own store columns, own delivery path in service/failure-alerts.ts). The
gateway validator only ran channel checks for delivery patches, so a
failure-alert-only patch stored an unknown channel unvalidated and only failed
later at delivery time with channel_not_found.

Add assertValidCronFailureAlert (reusing the announce-channel validation), wired
into create + update. It mirrors resolveFailureAlert() runtime resolution:
resolves the effective mode (job or global cron failure-alert mode; webhook alerts
skip channel-type validation), inherits the job delivery channel/target when the
alert names none (rejecting a routing-changing edit that would activate a
legacy-invalid inherited channel, while unrelated/threshold edits and already-
active alerts are not blocked), resolves a provider-prefixed target like the
delivery/failureDestination paths, and honors the channel:null last-fallback. Maps
failureAlert.channel errors to INVALID_REQUEST. Regression tests included.

Closes #103864

* fix(cron): align failure alert route validation

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 22:24:41 -07:00
Peter Steinberger 7014d72752 refactor(ui): unify sidebar row visibility (#112511)
* refactor(ui): unify sidebar row visibility

* test(ui): consolidate sidebar visibility coverage

* style(ui): restore chat view line budget

* chore(ui): drop superseded lint workaround
2026-07-21 22:19:28 -07:00
Peter Steinberger f236e83de7 refactor(channels): shrink ChannelSetupInput to a generic envelope with a deprecated compatibility tier (#112319)
* refactor(channels)!: shrink ChannelSetupInput to a generic envelope with a deprecated compatibility tier

* fix(channels): keep ChannelSetupInput structurally assignable without an index signature

* docs: regenerate docs map
2026-07-21 22:17:03 -07:00
Andrey Bugaev 2727b6ec23 Fix live orphan session transcript visibility (#92261)
* Fix live orphan session transcript visibility

* Keep live orphan fallback internal

* Remove unnecessary transcript fallback rename

* test(memory): preserve orphan visibility coverage

* fix(memory): scope orphan transcript fallback

* fix(memory): require agent-wide orphan visibility

---------

Co-authored-by: Andrey Bugaev <370409306+skocher@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 22:16:07 -07:00
Josh Lehman cb797c959a feat(wizard): narrate app-recommendation scan phases in the progress spinner (#112414) 2026-07-21 22:13:36 -07:00
Peter Steinberger d823cdc794 fix(ui): normalize nullable workspace conflict in chat-view notices 2026-07-21 22:06:08 -07:00
Josh Lehman 4481c623cd fix(onboard): survive inference owner drift and prefer subscription logins in guided setup (#112378)
* fix(onboard): survive inference owner drift and verify credentials route-aware

Guided onboarding crashed ("Could not start the CLI") on the openai-api-key
candidate when OPENAI_API_KEY was set and a Codex CLI login existed:

- owner revalidation resolved provider auth without the route model's
  id/api, so the transport gate never applied and profile-first discovery
  picked the Codex-imported ChatGPT OAuth profile instead of the env key
  the probe ran with — a deterministic fingerprint mismatch
- that mismatch escaped the activation persistence path as a plain throw,
  crashing the wizard ladder instead of moving to the next candidate

Owner re-resolution now carries resolved model transport facts (fail closed
when the model cannot be resolved), and all setup revalidation sites route
through one helper whose drift error activation maps to
{ ok: false, status: "auth" }.

* feat(onboard): prefer logged-in subscription CLIs over env API keys in setup ladder

* fix(onboard): promote codex only on verifiable ChatGPT OAuth tokens

* fix(onboard): surface detected AI candidates in the top auth-choice tier

* fix(onboard): name detected candidates and the current model clearly

* test(setup): mock model resolution in the bound-session lock test

* fix(system-agent): carry verified model transport facts
2026-07-21 22:03:26 -07:00
Peter Steinberger c7dd7b4be2 fix(pr): rebuild stale prep branches after head changes (#112510)
* fix(pr): refresh stale prep branch on head drift

* fix(ci): repair PR landing gate failures
2026-07-21 21:57:56 -07:00
Peter Steinberger adf81e14a8 refactor(ui): split notice rendering out of chat-view to restore max-lines headroom 2026-07-21 21:55:43 -07:00
Peter Steinberger 9231bcb38f fix(macos): keep permissions reachable on short screens (#112507)
* fix(macos): keep permissions reachable on short screens

* fix(macos): preserve onboarding i18n inventory
2026-07-21 21:53:07 -07:00
Jason (Json) 735a6acd56 fix(codex): label unnamed sessions from previews (#112497) 2026-07-21 22:53:05 -06:00
Alix-007 ce905af286 fix(vydra): apply request policy to media generation requests (#105884)
* fix(vydra): apply request policy to media generation requests

* fix(vydra): normalize body deadline aborts
2026-07-21 21:49:40 -07:00
Alix-007 17006d7de5 fix(zalo): prevent Bot API requests from hanging (#111636) 2026-07-21 21:49:14 -07:00
Hiroshi Tanaka 52f412bf17 fix(browser): tab creation steals window focus during agent automation (#105356)
* fix(browser): tab creation steals window focus during agent automation

Agent-created tabs inherited CDP's foreground default: direct CDP
Target.createTarget omitted the background flag, and the extension
relay's createTab defaulted to active:true, so every agent tab open
activated the new tab (and, on the extension driver, focused the
window), interrupting whatever the human was doing in that browser.

Direct CDP tab creation now requests background:true (agent tab
ownership/selection is target-id based and never depended on
activation), and the extension relay defaults an omitted background
to true while preserving an explicit background:false, matching the
Codex/Claude-in-Chrome model the extension driver mirrors.

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

* refactor(browser): keep focus fix LOC-neutral

Preserve background tab creation while keeping the oversized CDP and relay modules within the current LOC ratchet.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* fix(browser): honor explicit CDP focus requests

Keep background-by-default automation while treating Target.createTarget focus=true as an explicit foreground request in the extension relay.

Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* fix(browser): preserve explicit CDP focus semantics

Apply the background-by-default automation policy only when focus is omitted, preserving focus=false foreground-tab requests as well as focus=true.

Codex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* fix(browser): preserve create target window focus

Carry the resolved CDP focus intent through the extension relay and explicitly focus the containing Chrome window when requested.\n\nCodex-Session: 019f5e93-780a-7350-88f9-1986cdb64914

* style(browser): refresh relay import order

* test(secrets): use secure node exec fixtures

* test(doctor): secure exec secret fixture

* test(doctor): retain narrowed temp path

* test(secrets): secure remaining exec fixtures

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-21 21:35:40 -07:00
Dallin Romney 8d3d472cbe docs(skills): require evidence-driven backport audits (#112506) 2026-07-21 21:28:50 -07:00
Peter Steinberger e81a2ce657 feat(ui): show chat run startup status (#112339)
* feat(ui): show chat run startup status

* refactor(agents): isolate run status emission

* chore(protocol): refresh startup status models

* refactor(swift): remove unused chat helpers

* test(swift): align retry and i18n fixtures

* fix(swift): restore outbox display helper
2026-07-21 21:25:23 -07:00
Peter Steinberger c780d8b1c0 feat(ui): unify agent pickers with avatars (#112488)
* feat(ui): unify agent pickers with avatars

* fix(ui): close agent picker on draft reset
2026-07-21 21:11:18 -07:00
Peter Steinberger d5d2d63ead fix(agents): resolve computer node ids against the full node list first (#112503)
resolveComputerNode passed only the eligible (computer-capable) nodes to the
shared resolver, so an explicit exact node id belonging to an ineligible
device was never scored. Resolution could then fall through to display-name
matching and select a different eligible machine whose display name equaled the
requested id, observing and acting on the wrong desktop.

Mirror the mobile_ui-tool fix: match an exact node id against the full node
list first, reject an ineligible exact match with the eligible ids listed, and
only then resolve by display name among eligible nodes (still rejecting
ambiguous collisions, now with eligible ids in the error). Split the
node-selection tests into computer-tool.node-resolution.test.ts to keep the
main test file under max-lines.
2026-07-21 21:09:19 -07:00
Peter Steinberger b83af8157b test(ui): reuse shared non-isolated workers (#112493)
* test: isolate OpenClaw home in shared setup

* test(ui): reuse shared workers for pure suites

* test(ui): align scoped runner contract
2026-07-21 21:08:12 -07:00