Disable fetch-triggered automatic maintenance at the PR source owner. Git 2.54+ can otherwise prune a sibling admin directory with a missing or empty backlink during healthy worktree entry. Keep the existing preservation assertions and align direct helper fixtures with the Darwin Bash guard.
Refs #147527. Reproduces the six containment failures from run 34800901928; three full containment runs pass after the fix. P1 autoreview and check:changed passed.
AI-assisted.
Supersedes #147381 by @LiuwqGit.
Closes#147346.
## What Problem This Solves
A working `sag` skill appears unavailable, and `doctor --fix` disables it, when its installed CLI obtains credentials outside the Gateway environment.
## User Impact
Installed `sag` stays available with alternate credentials. The executable checks credentials when it runs. Optional configured-key injection remains available.
Doctor does not automatically re-enable entries disabled by an earlier run. The saved flag does not distinguish Doctor repair from an intentional user choice. If the earlier disablement was incorrect, run `openclaw config set skills.entries.sag.enabled true`. Refresh the Skills list; the next agent turn uses the refreshed skill settings.
## Why This Change Was Made
The bundled skill declaration keeps its executable requirement and removes the incorrect environment prerequisite. The original metadata fix and authorship are preserved. The regression now runs registered `skills info sag --json` and stopped-Gateway `doctor --fix`, including the saved enable flag, instead of calling the status helper directly.
## Evidence
| Check | Main | This change |
| --- | --- | --- |
| Real CLI and Gateway `skills.status` | Needs setup; not visible | Ready; visible |
| Control UI Skills list | Under Needs Setup | Under Ready |
| Skill details | Missing-variable warning | Warning gone; key editor retained |
| Stopped-Gateway Doctor | Saves `enabled=false` | Preserves absent or explicitly true enablement |
| Registered CLI regression | Four expected failures | Four passes |
Correlated request/response frames confirm that both the browser and CLI received `skills.status` from the Gateway. The installed executable's alternate key-file check uses a local test endpoint; live-account validity and audio production are not claimed.
Fresh merge `489365ccffab2e043d676ed3b01cb2e0b5a203d4` has candidate parent `40632360f3ff8162fa27503e08c636223c8cc852` and main parent `4750ff8d2b`. It passes 4 registered CLI regressions, 44 skill tests, 10 Doctor tests, and 153 test-registration checks. Changed-file lint, formatting, and whitespace checks pass. Main's regression run used `d0cf628ff2` with the same test and unchanged main metadata.
The process test uses the existing isolated CLI project. Fixed test owners and CI job counts remain unchanged; generated compact group placement can change as the test inventory grows. Readiness does not establish live-account validity or successful audio output.
### Skills list
| Before | After |
| --- | --- |
|  |  |
### Missing requirement and key editor
| Before | After |
| --- | --- |
|  |  |
## Consumers
- Discovery, Gateway and CLI status, both Doctor skill checks, onboarding, summaries, and recommendations read the same prerequisite declaration.
- The Control UI list and agent controls consume the corrected status; the optional key editor remains available.
- Runtime selection reads the same metadata. New snapshots preserve optional key injection; existing snapshot refresh rules remain unchanged.
- Native clients consume the existing response. The macOS binary-trust reader uses the unchanged binary requirement.
- Explicit disablement, allowlists, agent filters, configured-secret isolation, and automatic-update Doctor protection remain unchanged.
## Compatibility
No new configuration key, schema, protocol, dependency, or runtime credential reader. Existing disabled entries are not automatically re-enabled. The skill prose assigns credential checking to the executable; readiness does not promise valid account credentials or successful speech generation.
Co-authored-by: LiuwqGit <liu.weiqin@xydigit.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* perf(workspace): offload inventory and manifest processing
Keep the Gateway and paired nodes responsive during large workspace transfers with bounded computation workers. Hosts retain session authority, Git processes, file writes, durable acceptance, and cleanup.
Use transferable UTF-8 payloads for supported Unicode inventories, preserve independent errors during cancellation, and compare already-decoded manifests without copying their object graphs between threads.
* test(workspace): finish manifest fixture ownership
* refactor(workspace): distinguish stage input implementation
* test: register workspace benchmark and honor system Bash
* fix(ui): load Home and System busyness inside their panels
* chore(ui): record approved immediate-panel startup budgets
* fix(ui): retain System busyness through automatic chunk recovery
* fix(ui): keep automatic diagnostic restores out of Settings
* chore(ui): refresh approved startup baseline against current main
Teams search and member-info now use an explicit channelId before current-conversation fallback while preserving existing read policy and direct target precedence.
Refs #115367.
* fix(sandbox): restore workspace files in Docker Gateways
Resolve managed workspace, agent, skill and nested bind sources from a verified Gateway container before sandbox hashing and creation. Share the effective mount plan across shell and browser lifecycles; preserve read-only permissions and refuse stale hot mounts with scoped recreate guidance.
Fixes#31331
Co-authored-by: AaronWander <siralonne@163.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
* test(sandbox): isolate managed mount permission fixtures
* fix(sandbox): narrow discovered Docker container ids
* test(sandbox): split container creation and mount coverage
* test(sandbox): restore filesystem fixture import
* test(sandbox): sort mount proof records immutably
* fix(sandbox): inspect typed Docker metadata and isolate E2E cleanup
* test(sandbox): assert package import follows fixture environment
---------
Co-authored-by: AaronWander <siralonne@163.com>
Co-authored-by: Frank Yang <frank.ekn@gmail.com>
The reviewed head is `de7fb2d7b072858c3b2b0370756fcdd31e237cbd`.
- Both embedded system-expert entries use the existing queue's dedicated one-slot inference lane. Ordinary agent concurrency remains unchanged. The outer tracking lane cannot join a shared capacity group because it waits for inner work.
- The same assistant runner serves command planning and caretaker greetings. Diagnostics exposes the added lane through its existing row list. No configuration key, schema, migration, protocol, or SDK change is required.
- The retained authenticated `openclaw.chat` and ordinary parent-tool captures show the expert reply and successful parent completion with Main concurrency one. The committed chat and greeting regressions both fail with the original main producers and pass with the fix.
- Fresh merge `9022ca9fccf808112a94eeea3099442c04396420`, with main parent `078ca0bc2f`, passed 107 tests across nine owner and sibling files. Its candidate parent `8531d0d5e5b9fcc4be6f061da10f7e5923f3185b` differs from the reviewed head only by the two evidence images that were later removed from the repository. Executable source and tests are identical.
- The proof uses a local response fixture. It establishes immediate reply/tool completion and queue settlement. It does not establish external generation or transcript replay continuity; the parent capture includes `replayInvalid: true`.
- Parent cancellation can still allow previously queued expert inference to start after the parent stops. This was observed on main and remains outside this lane repair.
- The inspected before/after Debug images show idle lane inventory, separate from the concurrency-one runtime experiment. The captures are published through the owner's evidence gist below; both images were inspected in chat and their published raw links were verified.
- Supersedes #147468 by @ekinnee, whose production commit is preserved under its original authorship. Thanks @maulu5 for the report in #147264. Closing the original PR remains part of landing.
CI run [34792848991](https://github.com/openclaw/openclaw/actions/runs/34792848991) passed at this head.
## Consumers
Embedded chat turns, command planning, caretaker greetings, and the Debug diagnostics row list retain their existing shared owners.
## Screenshots
Gateway lane diagnostics, sanitized captures (before on main, after on this branch).
| Before | After |
| --- | --- |
|  |  |
Co-authored-by: Erick Kinnee <ekinnee@gmail.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Extend the existing model matrix with isolated Gateway tasks, fixed-workload build comparisons, and separate task and interview evidence. Preserve failed trials, exact source identities, task effects, logical cell completion, and observed preview coverage.
Validation: 187 focused tests, changed-file and targeted type/lint/docs checks, exact-candidate runtime build, actual OpenAI smoke, read-only replay of 24 original trials plus the final smoke, and fresh P2 review. Original scores and interview qualifications remain preserved.
Isolate the native hook relay build graph while preserving readonly state lookup, explicit policy decisions, and the lazy authenticated Gateway fallback.
Cancel disconnected request waits through the existing approval authority. Keep duplicate callers independently cancellable, retain unbound durable approval deduplication, and detach exact relay-owned entries before callbacks so old cleanup cannot remove a successor. Observe already-started promises when synchronous cancellation wins.
Update managed Codex to the official 0.154.0 release and align its version fixtures and current documentation. This improves lifecycle ownership and reduces the relay import closure; it does not cap hook concurrency, prove faster bursts, or establish resolution of the historical constrained-host timeout.
Related: https://github.com/openclaw/openclaw/issues/91009
Thanks to @nvtoroy for the constrained-host captures and guarded opt-out evidence in https://github.com/openclaw/openclaw/pull/121668 and https://github.com/openclaw/openclaw/pull/111205. The opt-out proposal remains distinct and unimplemented by this change.
* fix(codex): route Bun history reads through built worker
* test(codex): align prepared auth restart requests
* fix(codex): recognize aliased Bun history workers
* test(codex): allow optional account read after restart
* fix(logging): share redaction state across module copies
Share the live registry, revision, and cached redactor while preserving independent captured snapshots. Include the singleton helper in frozen publication tooling and its fixture.
* test(agents): keep live read arguments within output budget
Use the fixture path relative to the configured session workspace so deep temporary roots do not exhaust the unchanged 128-token model limit before a tool call completes. Preserve all redaction and continuation assertions.
* refactor(test): centralize worker declaration metadata
Replay the reviewed first tooling layer on the current frozen main base. Keep package activation declarations reserved for the later owning layers; preserve the inherited main build graph and test coverage.
* fix(update): bind recovery admission to existing authority
Replay the reviewed authority layer on current main, preserving the diagnostics import owner. Retain Json (fuller-stack-dev) rollback-journal and Bun regression coverage; restore NORMAL reader policy after rollback-mode admission so retained Bun statements do not hold locks after settlement. Later FD3 custody remains in its owning layer.
* fix(config): retain authority across config persistence
Replay the accepted config authority layer without behavioral changes. Preserve producer-owned write guards through backup, snapshot, persistence, reread, and error settlement.
* fix(plugins): fence convergence with lifecycle authority
Replay the accepted plugin authority layer without behavioral changes. Keep install-record, peer-link, retention, doctor repair, and cohort operations under their existing canonical lease owners.
* fix(plugins): preserve first authority refusal during repair
Keep authority failures outside filesystem warning conversion, retain the first callback refusal through normalized installer outcomes, and join admitted peer repairs before rejection. Preserve the synchronous peer guard and lease-bound index CAS finalizer.
Adapt the Doctor and convergence ownership pattern from Jason Sy in #144130. Focused red/green: 23 failures became 32 passes; full peer and retention controls pass 37 cases. Native review raised an overlapping async callback scenario; source review rejects it because the current per-invocation Doctor path is serial. Root final-effect and installed integration gates remain open.
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
* fix(config): refuse guarded include writes before effects
Reject include-owned mutations carrying inherited authority, explicit assertCurrent, or beforeCommit before Root preparation and backup effects. Remove the unreachable guarded include publisher and retain ordinary include publication and custom-root IO ownership.
Three missing-refusal regressions reproduced before the repair. All 107 cases in mutate, io.write-lock and io.write-reread pass, including ordinary include exclusion and compensation controls. Native P1 review is scoped-clean. The fs-safe final-effect contract and installed candidate integration remain separate draft gates.
* fix(config): retain update authority through runtime activation
* fix(plugins): repair leased authority CI coverage
Remove the unused unleased record writer and seed test fixtures through the canonical store producer. Keep compiled Doctor fixture module identity and direct leased-writer assertions.
Bind registry authority callbacks and correct the focused fixture typing and lint errors without weakening refusal checks. Independent source review and native P0/P1 review passed; runtime and hosted CI qualification remain pending.
* test(plugins): omit redundant deferred type arguments
Use the existing void generic default for the three deferred test controls. The correction emits byte-identical JavaScript and preserves all assertions.
This trivial test-only delta was independently verified after the full L4 P0/P1 review. The earlier focused 295-test and selected typecheck passes remain source-bound; the failed lint surface and unrun export scans still require qualification.
* test(plugins): cover synchronous host-link admission turns
Retain the three filesystem API-entry scheduling controls contributed by Jason Sy (@fuller-stack-dev) in https://github.com/openclaw/openclaw/pull/144316#issuecomment-5632474077.
Cover missing node_modules, stale symlink, and package-copy replacement while preserving the existing synchronous authority contract and test seed helper. These controls observe API-entry timing, not native filesystem-effect atomicity or an observed regression on this source.
Independent exact-block review and fresh full L4 native P0/P1 review passed. Targeted execution of these added cases remains pending.
* fix(plugins): retain updater authority through package settlement
* test(plugins): verify publication across updater revocation
* fix(test): satisfy updater authority lint rules
* test(plugins): isolate explicit update home fixture
* refactor(plugins): centralize installed update options
* style(plugins): format retained settlement fixture
* test(plugins): accept capabilities in retained settlement proof
* test(plugins): type retained settlement controls
* fix(plugins): preserve lifecycle refusal across persistent effects
Latch ownership refusal within install-record commits and forward the composed plugin lease to post-core peer effects. Add real-boundary regression controls for transient lease reads and raw plugin lease revocation.
Independent and native source reviews passed. Matching targeted formatting passed; runtime, type, lint, and packaged qualification remain pending.
* refactor(plugins): consolidate successful update records
Keep source-specific install metadata while recording capability consent and the completed install through one shared path. Protect installed-version precedence over embedded ClawHub metadata.
* test(update): join legacy finalization fixtures before cleanup
* test(update): use supported parameterized timeout options
* fix(plugins): share lifecycle refusal with package settlement
Keep the first lifecycle authority refusal visible to outer retained
package transactions after metadata publication, including transient
lease reads. Preserve ordinary-error and fresh-owner recovery paths.
---------
Co-authored-by: Jason (Json) <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
## What Problem This Solves
A waited `sessions_send` to an agent's own visible child starts duplicate reply and announcement work after the child's reply already returned inline.
Supersedes #144320 by @ylcn91. Closes#144265, reported by @tonyisblind.
## Why This Change Was Made
Use the durable requester key and stored spawn lineage in the existing send owner. Suppress the extra work only when the reply returns inline; keep the continuation when the wait expires. Preserve the reload handling from #146799.
## User Impact
The parent receives one inline child reply without re-entering the child. Late results still reach the parent. No configuration, storage, or protocol change is required.
## Evidence
Real Discord recordings captured the same registered spawn/send flow:
```text
main a2b2391e35: reply inline, delivery=pending, extra parent calls=1, extra child calls=1
candidate fe90c7249869: reply inline, delivery=skipped, extra calls=0
wait expiry: accepted/pending, then the held child reply reached the parent
```
The same two-turn QA direct-message Gateway test failed on unfixed main `6f58faf3eb` (exit 1): the inline reply had pending delivery and one extra parent reply step. It passed unchanged on the candidate and fresh merge (exit 0), with exact parent lineage, one child send, and no extra reply/announcement calls. Title requests were counted separately.
188 tests passed on merge `f62c21d708b4` with parents `fe90c7249869` and main `6f58faf3eb`, including the reload sibling. Commands:
```sh
node scripts/run-vitest.mjs src/agents/openclaw-tools.sessions.test.ts src/agents/tools/sessions-send-tool.a2a.test.ts src/agents/tools/openclaw-tools.spawn-session-key.test.ts src/agents/tools/sessions.test.ts
OPENCLAW_E2E_USE_PREBUILT_DIST=1 OPENCLAW_PROOF_VISIBLE_CHILD_SEND=1 node scripts/run-vitest.mjs run --config test/vitest/vitest.e2e.config.ts src/gateway/gateway.sessions-send-hot-reload.e2e.test.ts test/e2e/qa-lab/runtime/sessions-send-visible-child.product-proof.e2e.test.ts
```
Formatting, source lint, assertion/file-size guards, unused-export scans, and architecture checks passed. CI owns typechecking.
The delayed recording reached the parent, then logged the existing final-announcement error `Async work scope is closed`, also observed on main. This change does not claim to repair that separate error.
## Consumers
The requester-key change also affects session visibility and label lookup, self-send detection, reply addressing, watch ownership, and inter-session provenance. These now use the same durable requester identity as spawn and session lookup. Authenticated caller routing and tool policy retain their existing inputs. The worker send path keeps its exact-session-instance restrictions.
Visible and hidden owned-child tests release a held reply after the sending caller returns, then check that the parent receives it and retained work settles. Exact-session-instance tests still forbid detached delivery and durable watches. The existing reload continuation scopes remain intact.
The separate final-announcement scope error remains excluded. Late-delivery evidence proves that the parent receives the held reply within the existing continuation window; it does not promise another public channel message or an unlimited wait.
Supersedes #144320 by @ylcn91, whose four commits retain their authorship. Thanks to @tonyisblind for #144265.
Co-authored-by: Yalçın Doksanbir <yalcindoksanbir@gmail.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Related: #146012. Supersedes #146205 by @MasterSwords1. Thanks @jalehman for the report. The contributor's four commits retain their authorship.
## What Problem This Solves
**Continue on Gateway** fails after confirmation when an offline device session has a pending workspace result, leaving the session blocked.
## User Impact
Confirmed abandonment returns the session to local use. A fresh turn completes, and normal deletion archives its transcript. Ordinary moves still preserve pending results. Unsynced device work can be lost, as the existing confirmation warns.
## Why This Change Was Made
The durable move intent is the single owner of the abandonment decision. It permits the pending-result drain; result recovery yields to it, and existing teardown retires the exact result and claim. The placement coordinator orders moves against recovery. No schema, migration, configuration, protocol, or dependency changes.
Tests now cover the full user flow and explicit fixture cleanup, removing overlapping handler tests and shutdown-error suppression. The correction commits remove 269 net lines from the contributor version. Remaining growth supplies three real Gateway regressions.
## Evidence
Real Gateway capture, using the same exact-source `sessions.move` request with `target: {kind: "gateway"}` and `abandonSource: true`:
| Main `a2b2391e35` | This change |
| --- | --- |
| `UNAVAILABLE: Cannot drain session … with a pending cloud workspace result` | `ok: true`, `placement.state: local` |
| Original claim and pending result remain | Pending result and move intent gone; old claim/result rejected |
| Recovery action blocked | One fresh reply: `RECOVERED_SESSION_OK`; deletion returns `deleted: true` with a readable transcript archive |
Commands: `pnpm openclaw gateway call sessions.move`, then `chat.send`, `agent.wait`, `chat.history`, and `sessions.delete`. The ordinary-move negative case still rejects. The old device cleanup record remains until its exact stop is acknowledged.
Fresh two-parent merge proof: candidate `0801a11ab50c` + main `6f58faf3eb` → `ec30ae86f2439`. The repository CI test runner (`node --import tsx scripts/ci-run-node-test-shard.mts`) passed **146 tests in 7 files**, using the Gateway core, server, and isolated-server configurations. Coverage includes move/store ownership, forced abandonment, recovery coordination, startup, fresh turns, and archived deletion. Formatting, changed-file lint, line limits, assertion safety, unused exports, and architecture checks pass. Typechecking remains with CI.
Startup cases prove **database reopen plus in-process Gateway startup**, including an already-failed placement with a different error. No physical-device shutdown or operating-system crash claim.
## Reviewed proof scope
The read-only review found no blocking source or test correction at `0801a11ab50cdf94e514951b36b68793bb58a0e5`.
- The real Gateway proof covers confirmed abandonment, one fresh reply, and exact-session deletion with a readable transcript archive. Ordinary moves still reject the pending result.
- The standalone capture used the same three production blobs as the final head. All three maintained full-flow cases also passed on merge `ec30ae86f24390d69e7af606aa7c50cc9683107a`, with candidate `0801a11ab50cdf94e514951b36b68793bb58a0e5` and main `6f58faf3eb` as parents. The selected suite passed 146 tests in seven files.
- Recovery coverage means database reopen plus in-process Gateway startup, including an already-failed placement with a different error. It does not claim a browser click, an operating-system crash, or physical-device shutdown.
- The old device cleanup record remains until its exact stop is acknowledged. The tests use an explicit synthetic acknowledgement only during teardown.
- The original contributor's four commits retain their authorship. Credit remains with @MasterSwords1 for #146205 and @jalehman for #146012. Closure of #146205 remains a landing step.
## Consumers
Confirmed `sessions.move` and startup recovery share the durable abandonment decision. Fresh chat turns and session deletion consume the resulting local placement; ordinary moves retain their existing pending-result guard. Session-change events refresh the existing placement projection.
Co-authored-by: MasterSwords1 <abderrahmaneriyad15@gmail.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* feat: give every plugin a compact chat activity icon
Separate package-owned activity SVGs from plugin identity artwork. Ship 154 defaults and seven exact tool overrides, preserving Echo and the progress claw. Include authenticated bounded delivery, safe mask rendering, packaging, and authoring guidance.
* test: declare Vite types for the activity asset browser test
* refactor: keep plugin artwork selection with catalog presentation facts
* test: scope activity browser types and simplify fixture copies
Repair release fixture inputs and expectations without changing production behavior: align the root OTel SDK guard, apply the existing SQLite busy policy to the independent writer, and preserve quiet versus visible failed-tool progress. Close unused DM defaults in the group-only fixture before real Doctor validation.
The reviewed three-file patch is unchanged after adopting the already-landed startup-size repair. Exact-head CI and all 24 runtime fixture tests pass, with retained artifacts, causal controls, source hashes, and owned-lease cleanup verified. No performance budget, scenario selection, permission, or timeout was relaxed.
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Remove the retired private loader factory, default-instance forwarder,
VITEST-only publication and reader, and ignored internal logger argument.
Keep lazy native import, concurrent/successful caching, rejection eviction,
platform-specific guidance and error causes in the existing module owner.
Move the four retained loader cases to its exported runtime boundary using
dependency mocks, with independent replacement witnesses for success-cache
retention and same-closure retry. Retire the matching reset-registry row and
retain the existing max-lines pragma. Production is net -37 lines;
tests and support are net +24. No SDK, config, dependency or storage change.
Validation: all 208 original, ported and candidate cases retained; original
success-eviction and sticky-rejection controls discriminated; 29 required
checks and nested Doctor 6-case selection passed. Native store/staleness
proof is real; loader platform/error proof is mocked, not all-platform live
coverage. Managed P2 review passed after one report-directory recovery;
the first attempt's unpublished verdicts remain unknown.