Skip to content

fix(status): show runtime in CLI sessions#77776

Merged
vincentkoc merged 2 commits into
mainfrom
fix-status-cli-runtime-info
May 5, 2026
Merged

fix(status): show runtime in CLI sessions#77776
vincentkoc merged 2 commits into
mainfrom
fix-status-cli-runtime-info

Conversation

@vincentkoc
Copy link
Copy Markdown
Member

Summary

  • Problem: openclaw status showed recent session model/tokens, but omitted the agent runtime/harness that /status already prints.
  • Why it matters: operators could not tell from terminal status whether a session was running through PI, Codex, ACP, or a CLI-backed runtime.
  • What changed: shared the /status runtime-label resolver, adds runtime labels to status summary rows, and renders a Runtime column in the CLI sessions table.
  • What did NOT change (scope boundary): no gateway runtime/service status semantics, no session migration, no runtime selection policy changes.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Related #
  • This PR fixes a bug or regression

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: CLI status sessions now include the same agent runtime/harness label used by /status.
  • Real environment tested: OpenClaw repo worktree on macOS; changed gate in Blacksmith Testbox tbx_01kqvpdtpmqnaamcqd7sjb6p26.
  • Exact steps or command run after this patch: see Repro + Verification.
  • Evidence after fix: targeted tests assert OpenAI Codex and OpenClaw Pi Default runtime rows; changed gate passed in Testbox.
  • Observed result after fix: sessions table rows include a Runtime field populated from shared status runtime label logic.
  • What was not tested: a live user session status printout with production channel credentials.
  • Before evidence: code inspection showed /status used resolveAgentRuntimeLabel while openclaw status session rows only rendered Model and Tokens.

Root Cause (if applicable)

  • Root cause: getStatusSummary() collapsed session metadata into SessionStatus without carrying the selected harness/runtime label, so the CLI renderer had no runtime field to print.
  • Missing detection / guardrail: session-row tests only covered key/kind/age/model/tokens/cache, not harness/runtime parity with /status.
  • Contributing context (if known): /status and CLI status had separate formatting surfaces even though they described the same session runtime concept.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/commands/status.summary.test.ts, src/commands/status.summary.runtime.test.ts, src/commands/status.command-sections.test.ts.
  • Scenario the test should lock in: status summaries carry runtime labels and CLI session rows render them.
  • Why this is the smallest reliable guardrail: the bug was data plumbing/rendering, so summary/runtime and row-format tests cover the exact seam.
  • Existing test that already covers this (if any): /status runtime labels already had coverage in src/auto-reply/status.test.ts.
  • If no new test is added, why not: N/A.

User-visible / Behavior Changes

openclaw status now shows a Runtime column in recent session rows.

Diagram (if applicable)

Before:
session store -> status summary -> CLI sessions table: Model, Tokens

After:
session store -> shared runtime label -> status summary -> CLI sessions table: Model, Runtime, Tokens

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: macOS locally; Linux Blacksmith Testbox for changed gate
  • Runtime/container: Node 22 / pnpm
  • Model/provider: N/A
  • Integration/channel (if any): N/A
  • Relevant config (redacted): N/A

Steps

  1. Inspect /status runtime-label path and CLI status summary/session-row path.
  2. Run targeted status tests.
  3. Run changed gate in Testbox.

Expected

  • openclaw status session rows include the agent runtime/harness label.

Actual

  • Fixed: session rows now include Runtime using the shared status runtime label resolver.

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Targeted proof:

pnpm test:serial src/commands/status.summary.runtime.test.ts src/commands/status.summary.test.ts src/commands/status.command-sections.test.ts src/commands/status.command-report-data.test.ts src/auto-reply/status.test.ts -- --reporter=verbose

Passed: 3 Vitest shards, including 18 unit-fast tests, 5 commands tests, and 68 auto-reply tests.

Changed gate:

pnpm testbox:run --id tbx_01kqvpdtpmqnaamcqd7sjb6p26 -- "pnpm check:changed"

Passed: lanes core, coreTests, docs; typecheck/lint/import-cycle/guard checks completed successfully.

Human Verification (required)

  • Verified scenarios: runtime labels from persisted harness metadata, summary propagation, CLI row rendering, and existing /status output tests.
  • Edge cases checked: empty sessions row keeps blank Runtime; default PI and Codex labels are rendered; ACP/CLI label behavior remains covered by existing /status tests.
  • What you did not verify: live production channel session output with real credentials.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps: N/A

Risks and Mitigations

  • Risk: Wider status table could wrap on narrow terminals.
    • Mitigation: uses the existing table renderer and compact labels already used by /status.

@vincentkoc vincentkoc self-assigned this May 5, 2026
@openclaw-barnacle openclaw-barnacle Bot added commands Command implementations size: M maintainer Maintainer-authored PR labels May 5, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented May 5, 2026

Codex review: needs maintainer review before merge.

Summary
The branch adds a CLI status Runtime column/field backed by the shared agent runtime label resolver, updates focused status tests, and adds a changelog entry.

Reproducibility: yes. Current-main source shows openclaw status recent session rows carry Model/Tokens but no Runtime, while the docs and /status runtime-label path already define that runtime distinction.

Real behavior proof
Not applicable: The external-contributor proof gate does not apply to this maintainer-labeled MEMBER PR, though the PR body includes after-fix test and Testbox evidence.

Next step before merge
Draft protected maintainer PR with no discrete repair finding; the next action is ordinary maintainer review, undraft, and merge gating rather than a ClawSweeper repair job.

Security
Cleared: No concrete security or supply-chain concern found; the diff is limited to TypeScript status rendering, tests, and a changelog entry.

Review details

Best possible solution:

Finish normal maintainer review, undraft when ready, and merge the narrow status summary/rendering patch if exact-head checks remain green.

Do we have a high-confidence way to reproduce the issue?

Yes. Current-main source shows openclaw status recent session rows carry Model/Tokens but no Runtime, while the docs and /status runtime-label path already define that runtime distinction.

Is this the best way to solve the issue?

Yes. Reusing the existing runtime-label helper and adding one summary field plus one table column is the narrow maintainable fix without changing runtime selection or session persistence semantics.

What I checked:

Likely related people:

  • vincentkoc: Authored merged adjacent runtime-visibility work for CLI sessions and Control UI sessions, including the shared status runtime label helper this PR reuses. (role: recent status/runtime visibility maintainer; confidence: high; commits: c874c0863ada, 16454f5c7ae1; files: src/status/agent-runtime-label.ts, src/commands/sessions.ts, ui/src/ui/views/sessions.ts)
  • Devin Robison: Local blame at the available history boundary attributes the current CLI status summary/table surfaces to a broad commit that added these files in this checkout history. (role: adjacent CLI status history owner; confidence: low; commits: 91879ac442d1; files: src/commands/status.summary.ts, src/commands/status.command-sections.ts, src/commands/status.command-report-data.ts)

Remaining risk / open question:

  • No tests were rerun because this was a read-only review; verification relies on source inspection plus the PR body's reported targeted/Testbox proof.
  • The added Runtime column widens the status table, so narrow terminal wrapping remains a small UX risk.

Codex review notes: model gpt-5.5, reasoning high; reviewed against c874c0863ada.

@vincentkoc vincentkoc force-pushed the fix-status-cli-runtime-info branch from 0259bff to e66fc3e Compare May 5, 2026 23:21
@vincentkoc vincentkoc marked this pull request as ready for review May 5, 2026 23:48
@vincentkoc vincentkoc merged commit 46c99cf into main May 5, 2026
87 of 89 checks passed
@vincentkoc vincentkoc deleted the fix-status-cli-runtime-info branch May 5, 2026 23:50
steipete pushed a commit that referenced this pull request May 6, 2026
* fix(status): show agent runtime in cli status

* fix(status): preserve configured runtime labels
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
* fix(status): show agent runtime in cli status

* fix(status): preserve configured runtime labels
ivorclarke added a commit to brightfire/openclaw that referenced this pull request May 11, 2026
* test(docker): align published upgrade timeout

* fix(plugins): recover managed-npm external plugins after package-manager upgrade

Co-authored-by: pingu <pingu@penchan.co>

* fix(doctor): repair allow-only official plugins

* fix(plugins): include json5 in memory runtime deps

* fix(plugins): include json5 in memory runtime deps

* chore(ci): allow bundled runtime json5 dep

* fix(openai-codex): avoid stale Responses replay state

* fix(openai-codex): match codex replay identity

* docs(changelog): credit codex replay fix

* fix(dashboard): guide manual token auth fallback

Summary:
- Add a redaction-safe dashboard fallback hint when tokenized URL delivery fails.
- Document the manual auth path and update the changelog.

Verification:
- PR CI exact head 48ccb97c0843c8b2e9640ac68adab6d311605705 green for relevant CI/security checks.
- pnpm test src/commands/dashboard.links.test.ts src/commands/dashboard.test.ts
- pnpm exec oxfmt --check --threads=1 src/commands/dashboard.ts src/commands/dashboard.links.test.ts
- pnpm format:docs:check
- pnpm docs:check-mdx
- pnpm docs:check-i18n-glossary
- targeted markdownlint for docs/cli/dashboard.md and docs/web/dashboard.md

* fix: sync Codex app-server protocol (#77578)

* fix: sync codex app-server protocol

* docs: add codex protocol changelog

* fix: refresh codex protocol schemas

* fix(telegram): derive media placeholders from MIME

Fixes #69793.

Verification:
- repro before fix: `pnpm test:serial extensions/telegram/src/bot-message-context.body.test.ts -- --reporter=verbose` failed 3 new cases with `<media:image>` returned for non-image/mixed saved media
- `pnpm test:serial extensions/telegram/src/bot-message-context.body.test.ts -- --reporter=verbose` passed 9 tests after fix
- `pnpm exec oxfmt --check --threads=1 extensions/telegram/src/bot-message-context.body.ts extensions/telegram/src/bot-message-context.body.test.ts`
- `git diff --check`
- `OPENCLAW_TESTBOX=1 pnpm testbox:run --id tbx_01kqtnnhpg6rk1225tbb7109kf -- "pnpm check:changed"` passed

* test(plugins): add kitchen sink rpc walk

* test: add slack onboarding channel smoke (#77575)

* fix: keep runtime prompt context out of system prompt (#77521)

* fix(plugins): keep explicit web providers on fast path

* test(agents): remove redundant payload casts

* Surface Codex usage-limit reset details in chat replies (#77557)

* fix(codex): surface usage limit reset details

* fix(codex): satisfy extension lint

* fix: surface codex runtime failures in tool-only replies

* fix(release): refresh plugin sdk api gate

Refresh release baseline hashes and raise the Plugin SDK API baseline heap cap so release preflight reports real drift instead of OOMing.

* fix(openai): route Codex audio to transcription model

* test(plugins): refresh kitchen sink docker fixture

* test(live): run cache probe with node

* fix(acpx): resolve plugin manifest from bundled runtime

* docs(changelog): credit @pashpashpash for Codex usage-limit reset surfacing

#77557 added user-facing surfacing of Codex app-server usage-limit reset
details and OpenClaw-owned runtime failure notices through tool-only
source-reply mode, but the entry landed without contributor attribution.
Add the merging PR ref and credit the human contributor @pashpashpash
per CLAUDE.md changelog-attribution rules.

* test(plugins): update kitchen sink prerelease canary version

* fix(discord): fail dropped final reply delivery

* docs: thank Discord reply fix contributor (#77596)

* Add instructions for how to setup slack for QA tests (#77606)

* docs(cli): document gateway restart --safe in command options

The `gateway restart` Command-options accordion only listed `--force`,
`--wait`, and `--json` even though `--safe` is a fully-supported flag
(documented in the prose at line 112 and rejected by lifecycle.ts when
combined with --force/--wait). Add --safe to the option list and a
Lifecycle-behavior bullet that explains the preflight-defer behavior
plus its mutual exclusion with --force and --wait, matching
src/cli/daemon-cli/lifecycle.ts:153-156.

* perf(plugins): reuse compatible metadata snapshots

Reuse compatible workspace-scoped plugin metadata snapshots for unscoped model catalog and manifest-contract readers while preserving env/config/workspace compatibility checks.

Also updates the stale kitchen-sink prerelease canary assertion to the current script default.

Fixes #77519.
Related #77532.

* fix(agents): mediate async media completions

* docs(help,security): cross-reference auth list and trusted-env-proxy

Two missing cross-references uncovered by the 24-hour doc audit:

- docs/help/faq-models.md: link to `openclaw models auth list` from the
  "What is an auth profile?" accordion. The command was added in
  23eb44b045 but the FAQ never pointed users at it.
- docs/security/network-proxy.md: list `tools.web.fetch.useTrustedEnvProxy`
  in Related Proxy Terms. The opt-in is fully documented in
  docs/tools/web-fetch.md but the proxy reference page omitted the
  cross-reference, leaving the page incomplete for proxy-state triage.

* test(live): retry cache probe text misses

* fix(secrets): preserve auth profile key refs during provider scrub (#77489)

* fix(secrets): preserve auth profile key refs during provider scrub

* Add changelog for secrets apply fix

* Seed auth profile ref for scrub regression

* fix(secrets): guard auth profile ref scrub

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* fix: repair stale session route state in doctor

* test: use latest kitchen sink canary

* build: bump axios override

* docs: require live proof before landing

* fix(media): use r+ for Windows media fsync (#76593)

Fix Windows media offload failures by opening saved attachment temp files read/write before fsync, preserving the non-truncating temp-file write path while allowing Windows FlushFileBuffers to succeed.

Also adds the required changelog entry.

Tests:
- pnpm test src/media/store.test.ts src/gateway/chat-attachments.test.ts
- pnpm check:changed

Thanks @qq230849622-a11y.

Co-authored-by: 李claw <264894741+qq230849622-a11y@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>

* fix(lsp): resolve Windows .cmd shims (#75343)

Resolve Windows npm .cmd shim startup failures for bundled LSP servers by routing LSP process spawning through the shared Windows spawn resolver with a sanitized child environment.

The change reuses existing PATH/PATHEXT and .cmd shim handling, keeps non-Windows behavior unchanged, and adds focused regression coverage for resolver wiring, env sanitization, and spawn materialization.

Fixes #75352.

Tests:
- pnpm test src/agents/pi-bundle-lsp-runtime.windows-spawn.test.ts src/agents/pi-bundle-lsp-runtime.test.ts
- pnpm check:changed

Thanks @ElliotDrel.

Co-authored-by: Elliot Drel <156480527+ElliotDrel@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>

* test(plugins): align metadata snapshot policy fixtures

* test(live): scale gateway profile timeout

* test(live): use low reasoning for cache probes

* feat(agents): add post-compaction loop guard module + config

Pure module with unit tests; not yet wired into runner. The guard arms
after auto-compaction-retry and aborts when the same (tool, args, result)
triple repeats within the configured window.

Refs #77474

* fix(agents): address review feedback on post-compaction loop guard

- Add PostCompactionLoopPersistedError.fromVerdict factory.
- Add unit tests for the error class + fromVerdict adapter.
- Disabled guard is now truly dormant (no state mutation when enabled=false).
- Tighten help text for postCompactionGuard.enabled.

Refs #77474

* feat(agents): wire post-compaction loop guard into pi-embedded-runner

Arms the guard at each of the three compaction-success points in
run.ts and observes tool-call outcomes from the diagnostic session
state's toolCallHistory after each attempt. Aborts with
PostCompactionLoopPersistedError when the same (tool, args, result)
triple repeats windowSize times within the post-compaction window.

Refs #77474

* fix(agents): make post-compaction guard config valid + observation trim-resilient

Two correctness fixes from code review.

1. Zod schema (src/config/zod-schema.agent-runtime.ts) was strict and
   rejected tools.loopDetection.postCompactionGuard.* keys at validation
   time, making the guard's documented configurability inaccessible at
   gateway startup. Adds ToolLoopPostCompactionGuardSchema with both
   optional fields and wires it into ToolLoopDetectionSchema.

2. The runner observation cursor in pi-embedded-runner/run.ts used
   absolute indices into state.toolCallHistory, but that array is
   trimmed at historySize (default 30). Once the buffer was full, new
   records shifted out from under the cursor and the guard silently
   missed every loop in long-running sessions. Replaces the index
   cursor with a monotonic toolOutcomeSeq on SessionState that
   recordToolCallOutcome bumps on each observable push (unmatched
   branch only, mirroring the prior cursor's effective semantics).
   The runner now reads the most recent (currentSeq - lastSeq) entries
   from the tail of toolCallHistory, which is trim-resilient.

Adds zod parse tests for the new config keys (valid, empty, unknown
key, non-positive, non-integer) and a runner regression test that
seeds toolCallHistory at the trim cap before triggering a
post-compaction loop, asserting the abort still fires.

Refs #77474

* fix(agents): observe matched post-compaction tool outcomes

* test(agents): avoid redundant guard scope spread

* fix(agents): observe post-compaction guard live

* refactor(agents): thread post-compaction guard observer

* fix(agents): honor scoped post-compaction guard config

* chore(config): refresh post-compaction guard labels

* refactor(agents): use loop detection switch for post-compaction guard

* fix(agents): abort post-compaction loops out-of-band

* chore(config): refresh merged baseline hash

* docs(channels): inline Slack manifest into Quick Setup with Recommended/Minimal variants

The Quick Setup steps in docs/channels/slack.md previously sent users to
the `#manifest-and-scope-checklist` anchor lower on the page to copy the
manifest, breaking the copy-paste flow. Pull the manifest inline as a
Mintlify <CodeGroup> for both Socket Mode and HTTP Request URLs tabs and
add a Minimal variant for workspaces that restrict scopes (drops
files:*, reactions:*, pins:*, mpim:*, emoji:read, usergroups:read while
keeping DMs, channel/group history, mentions, App Home, and slash
commands). Recommended matches extensions/slack/src/setup-shared.ts.
Existing Manifest and scope checklist section stays as the canonical
per-scope reference.

Cross-link from docs/concepts/qa-e2e-automation.md so QA maintainers see
the production manifest reference, while keeping the QA Driver/SUT pair
of manifests inline (the lane intentionally needs two distinct apps so
its shape is different from a single-app production install).

* docs(doctor): clarify configured plugin repair (#77613)

* ci(release): speed up focused release reruns

* fix: honor embedded runtime tool allowlists (#77609)

* fix: honor embedded runtime tool allowlists

* fix: preserve plugin allowlist filtering

* fix: gate bundled lsp allowlists

* docs(channels): add Socket vs HTTP comparison and explain shared URL fields

The Slack docs jumped straight from intro into the Quick Setup tabs
without telling readers when to pick each transport. Add a Choosing
Socket Mode or HTTP Request URLs section above Quick Setup with a
concern-by-concern table (public URL, outbound network, tokens, dev
laptops, scaling, multi-account, slash command transport, signing,
recovery) plus a Note pointing at the right default for each shape.

Also add an Info block under the HTTP Quick Setup manifest explaining
why the manifest carries three url fields (slash_commands[].url,
event_subscriptions.request_url, interactivity.request_url) — Slack's
manifest schema requires them spelled out separately even though
OpenClaw routes by payload type, and slash commands silently no-op
without their url field in HTTP mode.

* fix(infra): skip POSIX tmp path on Windows (#73533)

Skip the POSIX `/tmp/openclaw` preferred path on Windows so temp files land under the trusted `os.tmpdir()`/`%TEMP%`-based `openclaw-<uid>` path instead of `C:\tmp\openclaw`.

Add regression coverage for Windows path selection and the WhatsApp media temp directory integration, plus a changelog entry.

Fixes #60713.

Tests:
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/infra/tmp-openclaw-dir.ts src/infra/tmp-openclaw-dir.test.ts extensions/whatsapp/src/media.test.ts
- pnpm test src/infra/tmp-openclaw-dir.test.ts extensions/whatsapp/src/media.test.ts
- pnpm check:changed

Thanks @juan-flores077.

Co-authored-by: Juan Flores <112629487+juan-flores077@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>

* chore(release): prepare 2026.5.4 beta 2

* fix(release): prune externalized plugin chunks

* fix(build): route externalized plugin chunks

* fix(build): route externalized plugin entry chunks

* fix: recover missing Codex bound threads

(cherry picked from commit a373468d825224c92051dc2e50b717fbe75c401c)

* fix(plugins): repair missing openclaw peer links on update

(cherry picked from commit 2e8761c5c1541496667201ba02716ab90eb24ee3)

* docs: note plugin peer-link update repair

(cherry picked from commit 712aa96a8fb3589bd39ab0c2e071395bc612ad1d)

* fix: start configured generation providers

(cherry picked from commit 0eb06caae3807679b23d2c20a5b464fa46fdc556)

* fix: slack mention-gating thread participation

(cherry picked from commit cf3ce08b910ee13f84ec04970f2d852dbbd36a32)

* fix: explain missing git during plugin install

(cherry picked from commit a91c17c426f9bf5c0e201f0da99064e088e251fa)

* fix(update): authenticate restart health probes

(cherry picked from commit b546aa91e19b3411ccdbc7c4189c2fdac9415869)

* fix(whatsapp): normalize onboarding allowlist numbers

Normalize WhatsApp onboarding allowlist entries to digit-only WhatsApp IDs and reject invalid owner-phone inputs during prompt validation.

(cherry picked from commit 68a500c465cc2a44561c46d8ee14a01e471097f7)

* fix(telegram): reuse preview for long text finals (#77658)

* fix(telegram): reuse preview for long text finals

* test(qa): cover long telegram finals

* fix(qa): satisfy extension lint

* fix(qa): keep telegram long final fixture to two chunks

* test(telegram): cover three chunk finals

* fix(telegram): force long final preview boundary

(cherry picked from commit e03fe1e28965c5edbf8735620757c2f5d28b29e7)

* fix(plugins): honor beta channel for auto installs

(cherry picked from commit b0f841ef37dbf3313487a3068a51c2751ddf4fb3)

* test: align beta plugin repair expectations

* fix(gateway): skip IPv6 loopback binding on Windows (#69701)

Bind the default loopback gateway listener only to `127.0.0.1` on Windows so libuv dual-stack `::1` behavior cannot wedge localhost HTTP requests.

Also keeps non-Windows dual-loopback behavior covered, replaces the redundant Windows passthrough test with guard coverage, and adds the required changelog entry.

Fixes #69674.

Tests:
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md src/gateway/net.ts src/gateway/net.test.ts
- pnpm test src/gateway/net.test.ts
- pnpm check:changed
- GitHub required checks: green

Thanks @SARAMALI15792.

Co-authored-by: saram ali <140950904+SARAMALI15792@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>
(cherry picked from commit 978bc53e80cccdc23d42324b18c4d20cd4749315)

* fix(agents): enforce exact skill path from <available_skills> [AI-assisted] (#74161)

Summary:
- The PR updates agents skill prompt guidance to require exact `<location>` paths for single- and multi-skill selection, adds prompt assertions, and records the fix in the changelog.
- Reproducibility: yes. Static source reproduction is enough: current main lacks the exact-`<location>` guard  ... illsSection()`, while the PR diff adds it to both selection branches and asserts the resulting prompt text.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix: enforce exact skill paths for all skill matches

Validation:
- ClawSweeper review passed for head 743c9840c117312646ff6065ce4939f6555c5c0b.
- Required merge gates passed before the squash merge.

Prepared head SHA: 743c9840c117312646ff6065ce4939f6555c5c0b
Review: https://github.com/openclaw/openclaw/pull/74161#issuecomment-4341488109

Co-authored-by: tianguicheng <tianguicheng@xiaomi.com>
Co-authored-by: sallyom <somalley@redhat.com>
(cherry picked from commit c739088d62b9e3589f6a5f9bb31cdc73688ca20f)

* fix(sandbox): support Windows drive-letter bind sources

Accept drive-absolute Windows sandbox Docker bind sources in config and runtime validation while keeping blocked-path and allowed-root comparisons case-insensitive for Windows drive paths.

Also remove a stale WhatsApp setup import that blocked extension lint after the rebase.

Co-authored-by: 6607changchun <84566142+6607changchun@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>
(cherry picked from commit d02fbc6116ed9cbd501ad6a1e4d08f3fc71c1dd8)

* chore(release): bump to 2026.5.4-beta.3

* chore(release): refresh plugin SDK API baseline

* fix(diagnostics): drop stale session recovery event cases

* ci: parallelize release publish workflows

* chore(release): bump to 2026.5.4

* chore(release): bump version to 2026.5.5

(cherry picked from commit c37871e77bc404e2151ded7432b8d1da21c95601)

* fix: recognize attachment message sends

(cherry picked from commit a0ea07e462f66d73bdbbd7cbd2e5d456c860ba60)

* test: cover generated media delivery evidence fallback

(cherry picked from commit add9a49c40f90353632a9153552cdce0b981bc8d)

* fix: avoid media completion fallback while announce pending

(cherry picked from commit b32d4c5255c5d3ad089bf9a8c6dc25cf9e46c563)

* fix: backport media completion fallback

* security: harden gateway container privileges

Adds cap_drop and no-new-privileges hardening for the bundled gateway Docker Compose services.\n\nThanks @VintageAyu.

(cherry picked from commit f9da4843652e28678839f9c0f927ae33840281ff)

* fix(auth-profiles): exclude format rejections from profile cooldown (#77280)

Merged via squash.

Prepared head SHA: f4188b4dc34cd78b0004e1f18f35d59947b44dca
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Reviewed-by: @openperf

(cherry picked from commit 31da1fe5b05caf2368d53a2027382349c28918cb)

* fix(update): stop dev updates after fetch failure

(cherry picked from commit c1a385df8395a48bb8bf108994aff8cb0d239e07)

* fix(gateway): flush initial openai chat stream chunk

(cherry picked from commit d520bc4cb6b335076f9093c8e1c7493e4d68a90c)

* fix(gateway): mark openai role chunks unfinished

(cherry picked from commit fd86ab2e50038eeffb9e106a6ffb77634c83a2b1)

* fix: restore Codex agent dir runtime import

(cherry picked from commit a6d88e3cd91fcd93f8c0c020814a7bcc235b058f)

* fix(gateway): skip media sidecar for unrelated HTTP routes

(cherry picked from commit d38e30e02cd12164e17d13555a2b78550bf631ac)

* fix(discord): show reasoning text in progress drafts (#78050)

* fix(discord): show reasoning text in progress drafts

* fix(discord): handle reasoning progress snapshots

* test: isolate usage-format models fixture

(cherry picked from commit d94e7f5114dcf4ee5dccb99eee5938d6355eb692)

* Tolerate corrupt plugins during update (#77706)

* fix(update): tolerate corrupt plugin state

* fix(update): preserve corrupt plugin proof state

* fix(update): narrow corrupt plugin warnings

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
(cherry picked from commit 8aa7b7a4ca177752f9b9ddc93494f03f1d8c24b9)

* fix(release): unblock 2026.5.5 validation

* fix(release): tighten xai and corrupt plugin checks

* fix(ui): show session runtime in sessions table

* fix(sessions): show runtime in sessions table

* fix(status): show runtime in CLI sessions (#77776)

* fix(status): show agent runtime in cli status

* fix(status): preserve configured runtime labels

* fix(gateway): cancel delayed maintenance on shutdown

* fix(cli): fast-path bare channels help (#77659)

* fix(cli): fast-path bare channels help

* fix(cli): normalize channels add argv gating

* fix(cli): restore channel add completion flags

* fix(update): avoid lint-blocked dev installs (#77181)

* fix(gateway): improve shutdown error visibility and add close timeout

Adds structured warning collection to gateway shutdown, preserves lifecycle timeout handling, and covers HTTP/WebSocket/subsystem warning paths.

Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>

* fix(tui): prevent orphaned terminal sessions (#77662)

* fix(tui): prevent orphaned terminal sessions

* fix(doctor): repair heartbeat-poisoned main sessions

* fix(tui): preserve startup tls respawn

* fix: harden tui and doctor recovery paths

* fix(agents): filter runtime context from context engines

- filter hidden runtime-context custom messages before context-engine assemble, afterTurn, and ingest fallback hooks
- preserve the pre-prompt/new-turn boundary after filtering
- add regression coverage for assemble, afterTurn, and ingestBatch fallback behavior

- pnpm test:serial src/agents/harness/context-engine-lifecycle.test.ts -- --reporter=verbose
- pnpm exec oxfmt --check --threads=1 src/agents/harness/context-engine-lifecycle.ts src/agents/harness/context-engine-lifecycle.test.ts CHANGELOG.md
- git diff --check origin/main...HEAD
- pnpm changed:lanes --json
- pnpm testbox:run --id tbx_01kqx8fy1ktpqczkcej2pgpryz -- "OPENCLAW_TESTBOX_REMOTE_RUN=1 pnpm check:changed"

* fix(core): avoid session export filename collisions (#77762)

* fix(tui): bound session list recency (#77752)

* test(live): classify provider HTTP 5xx as server drift

* fix(hooks): avoid session memory filename collisions

Add collision suffixes for session-memory fallback filenames so repeated same-minute reset/new captures do not overwrite earlier archives.

* fix(gateway): keep reset and refresh paths responsive (#77701)

* fix(hooks): keep session memory slugging off reset hot path

* fix(hooks): run session memory capture asynchronously

* fix(cli): avoid stuck gateway command exits

* fix(gateway): cache empty read-only model catalog

* fix(doctor): stop stale TUI clients for WhatsApp responsiveness

* feat(status): show uptime in chat status

Show compact Gateway process and host system uptime in chat /status output.

* fix(video): recover generation parameter fallbacks

* fix(plugins): sync official plugin installs during update (#78065)

* fix(plugins): sync official npm installs during update

* fix(plugins): sync official clawhub installs during update

* test(update): mock official plugin sync helpers

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>

* fix(doctor): repair legacy Codex route config

Repair legacy openai-codex route config and session pins safely.

* fix(cli): repair legacy config before update channel switch (#77069)

* fix(cli): repair legacy config before update channel switch

* docs(changelog): note update channel legacy config repair

* fix(update): keep legacy config repair doctor-owned

* fix(update): keep dry runs read-only

* fix(update): avoid include-flattening legacy repair

* chore(release): prepare 2026.5.5 beta 1

* chore(release): prepare 2026.5.5 beta 2

* docs(release): clarify unpublished beta tag movement

* chore(release): keep 2026.5.5 beta 1

* chore(release): refresh release metadata for 2026.5.5 beta 1

* fix(discord): avoid false heartbeat ACK timeouts

Fix the Discord Gateway heartbeat scheduler so ACK timeout checks are measured from the actual heartbeat send, not from the fixed HELLO-time interval. This prevents late randomized first heartbeats from causing false reconnect loops while the Discord channel is still awaiting readiness.\n\nVerification:\n- pnpm test extensions/discord/src/internal/gateway-lifecycle.test.ts extensions/discord/src/internal/gateway.test.ts\n- pnpm exec oxfmt --check --threads=1 CHANGELOG.md extensions/discord/src/internal/gateway-lifecycle.ts extensions/discord/src/internal/gateway-lifecycle.test.ts extensions/discord/src/internal/gateway.test.ts\n- git diff --check\n- Real behavior proof check passed on PR head bf239b886020c11d55af33f16674e953535f9b4c\n\nFixes #77668.\nSupersedes #77956.\nThanks @bryce-d-greybeard and @NikolaFC.

(cherry picked from commit b5c33bc204ef566438d7a849ee506930a66f691e)

* fix: cap memory wiki filenames for safe writes

(cherry picked from commit ebb8bed78f909365e8c5b557908bc0ee89244b41)

* fix(discord): route guild text commands (#78080)

(cherry picked from commit d7bd9fe0490c72f24a6f20bbc7789f84822b1333)

* fix(sessions): restore Control UI /new hooks

Fixes #76957.

Restores the Control UI /new hook lifecycle through an explicit sessions.create emitCommandHooks opt-in, preserving hook-free defaults for programmatic parent-session creates.

Validation:
- pnpm protocol:check
- pnpm test src/gateway/server.sessions.reset-hooks.test.ts ui/src/ui/app-render.helpers.node.test.ts
- pnpm exec oxlint on touched TS files
- pnpm exec oxfmt --check --threads=1 on touched files
- git diff --check
- OPENCLAW_LOCAL_CHECK=1 OPENCLAW_LOCAL_CHECK_MODE=throttled env NODE_OPTIONS=--max-old-space-size=4096 pnpm check:changed
- GitHub PR checks green on 3a446ec78eb258df9ea34e2659ae34d3d5b56e5b
- ClawSweeper re-review completed with no blocking findings and security cleared

Duplicate triage:
- #77376, #77004, and #76967 were superseded closed attempts for #76957
- #77562 is a closed duplicate issue
- #77880 mentions #76957 but is not a duplicate of this hook fix

(cherry picked from commit 49c4a13231a3076226ecbd2e5069a029cdcc9e34)

* test: pass env to fallback metadata snapshot

(cherry picked from commit be1c99b76a59ed358ae75131d0d8504efa3200b3)

* fix(plugins): repair managed npm openclaw peers

Remove stale managed-root openclaw manifests, locks, hidden locks, and installed copies before npm plugin installs.

Relink plugin-local openclaw peer symlinks after shared-root npm install, rollback, update, and uninstall mutations so SDK-using plugins keep resolving openclaw/plugin-sdk/*.

Force safe npm commands out of inherited legacy/strict peer-dependency modes.

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
(cherry picked from commit 8e533490ab0a94fec8b3bdb3b184ebb5ce2edaba)

* fix(feishu): keep topic sessions stable

Fixes Feishu native topic starter routing by hydrating a missing topic thread ID before session resolution.\n\nCloses #78262.

(cherry picked from commit 8cc762daff13330810be0ad0f74dd50ccc8fed02)

* chore(release): prepare 2026.5.5 beta 2

* fix: show Codex tool progress in channel drafts (#77949)

Summary:
- Normalize Codex app-server dynamic and native tool activity into channel-visible tool progress.
- Keep Telegram message-tool-only progress drafts visible without duplicate dynamic item/tool lines.
- Preserve suppressed item progress while avoiding duplicate tool callbacks.

Verification:
- OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test extensions/codex/src/app-server/event-projector.test.ts extensions/codex/src/app-server/run-attempt.test.ts extensions/telegram/src/bot-message-dispatch.test.ts src/auto-reply/reply/agent-runner-execution.test.ts src/auto-reply/reply/dispatch-from-config.test.ts --pool=forks --maxWorkers=1
- pnpm tsgo:extensions:test
- pnpm exec oxfmt --check --threads=1 CHANGELOG.md extensions/codex/src/app-server/event-projector.ts extensions/codex/src/app-server/event-projector.test.ts extensions/codex/src/app-server/run-attempt.ts extensions/codex/src/app-server/run-attempt.test.ts extensions/codex/src/app-server/tool-progress-normalization.ts extensions/telegram/src/bot-message-dispatch.ts extensions/telegram/src/bot-message-dispatch.test.ts src/auto-reply/get-reply-options.types.ts src/auto-reply/reply/agent-runner-execution.ts src/auto-reply/reply/agent-runner-execution.test.ts src/auto-reply/reply/dispatch-from-config.ts src/auto-reply/reply/dispatch-from-config.test.ts src/infra/agent-events.ts
- pnpm lint:extensions
- pnpm build
- CI on 6ff6a1f86838a4cd5b0a344d4e4602a996bffb29: 88 success, 20 skipped, 1 neutral, no failures or pending checks

Fixes #75641.

* fix(line): require wildcard for open dm policy

* chore(matrix): remove stale extension changelog

* chore(release): prepare 2026.5.5 final

* test(line): narrow open dm policy parse result

* chore(release): refresh base config schema

* fix(release): tolerate optional plugin beta tag mirror failure

* fix(release): stabilize final validation checks

* ci: narrow MiniMax release live gateway lane

* ci: cap native MiniMax release live gateway lane

* ci: harden release validation harness checks

* ci: fix release cross-os loader path

* fix: normalize symbolic fetch headers

(cherry picked from commit 79f21a44426773237d8d8c429ea561e72b58c8a1)

* fix: normalize debug proxy fetch headers

(cherry picked from commit 96f80fa3ffe1dd6230cd3c8a622df1130f87254c)

* chore(release): bump version to 2026.5.6

* chore(release): update generated config schema version

* docs(release): trim 2026.5.6 changelog

* Revert "fix(doctor): repair legacy Codex route config"

This reverts commit 258e153705a7b839bbfa9667d8fd3af455ec1257.

(cherry picked from commit c8fcc46978c5b87f0149e3b1727d8a4ce36c72c5)

* fix(net): bound guarded fetch dispatcher cleanup

(cherry picked from commit 2465217b238ac50413fc5051dd1884504050970d)

* docs(release): note web fetch timeout cleanup

* test(net): cover stalled dispatcher close after fetch timeout

(cherry picked from commit b559fce7a1a69cd2bdf046796800821584380bbc)

* chore(release): refresh config baseline hash

* test(plugin-sdk): satisfy fetch header lint

* fix(release): harden ClawHub plugin publish

* chore(release): prepare 2026.5.7

* fix(plugins): apply npm overrides to managed roots (#78386)

(cherry picked from commit 5d557171b3cd19fd9855dd3522b647f6aed7d570)

* fix(plugins): skip managed npm peer resolution (#78348)

(cherry picked from commit aa9247e0cef35965217e5725b36a4562fa368eb4)

* fix(plugins): preserve legacy peer mode in managed npm installs

* fix(discord): prompt agents to suppress link embeds (#78614)

* fix(discord): prompt agents to suppress link embeds

* fix(discord): tighten link embed prompt

(cherry picked from commit 197edaa33d7b1e5faf52bd3b7a3a5014922a6eb1)

* fix(discord): keep agents quiet when others are addressed (#78615)

* fix(discord): keep agents quiet when others are addressed

* fix(groups): tighten addressed-elsewhere prompt

(cherry picked from commit 9c7c0ae891e887ea2d150376d3aee7c0d384588d)

* fix: skip npm uninstall when managed root is absent

(cherry picked from commit 3e8b5b4ee70d12357035260dc6dbfdf61f1fcde3)

* fix: clean stale managed npm plugin deps on uninstall

(cherry picked from commit 858038320dcb3ae022360475df17b91334798403)

* fix(docker): avoid package node_modules copy conflicts

(cherry picked from commit ffd212ca4338848a4e27f71fcc346347ee02b65c)

* fix(docker): preserve functional image dependencies

(cherry picked from commit 445dda54f142b9d685a331fb6eb805642311f821)

* fix(infra): avoid redundant usage summary refresh

(cherry picked from commit 2daf3d332ff0bb951cc89d968dc5f60869ab7f3d)

* fix(plugins): reconcile managed npm uninstall backports

* fix(ci): keep cross-os matrix resolution dependency-free

(cherry picked from commit d70e06334e38c0be1d984b0661e622199b764573)

* fix(ci): reject mixed-case staging debris before pack

(cherry picked from commit c738539b1e1dc33d23ff25faf400184462aa6c12)

* fix: preserve provider auth alias scope

(cherry picked from commit bc97182d71cd15c13e821c23e1af6095f468999e)

* fix(discord): parse provider-prefixed channel targets (#78625)

* fix(discord): parse provider-prefixed channel targets

* fix(discord): resolve allowlisted numeric dm targets

(cherry picked from commit 51356620e968a3cc460b6cdec03eaedc28686640)

* fix: clamp compaction max_tokens to model output limit (#54392)

Merged via squash.

Prepared head SHA: 8a888213edda9552be694d6d4c9d321bce0e3e50
Co-authored-by: adzendo <246828680+adzendo@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman

(cherry picked from commit ac4313598472fe1c0ea1cce24128337f6808138d)

* fix gateway optional plugin startup (#78642)

(cherry picked from commit 5572ee1a1a9058ad72a26ad5e49a1230aafba8ba)

* fix(cron): repair bad persisted model sentinels (#78641)

* fix(cron): repair bad persisted model sentinels

* test(cron): relax model preservation assertion

(cherry picked from commit 6aafdf121ac468ed31f5278916732cc6605be952)

* fix: reuse scoped provider auth metadata

* [AI-assisted] fix(agents): invalidate context engine cache (#78163)

Merged via squash.

Prepared head SHA: 6ed3add79759107e1e77053cde93014d475400b3
Co-authored-by: brokemac79 <255583030+brokemac79@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman

(cherry picked from commit 609a5d70a5501b230f4f8cff6aabe8ac537f6e8a)

* fix(cron): repair stale future next-run slots (#78272)

* fix(cron): repair stale future next-run slots

* fix(cron): repair stale future next-run slots

* fix(cron): repair stale future next-run slots

* fix(cron): repair stale future next-run slots

* fix(cron): repair stale future next-run slots

* fix(cron): repair stale future next-run slots

* fix(cron): repair stale future next-run slots

(cherry picked from commit 7175b1b5c63409b09f9d50baa5cf438a6dad8ed2)

* fix(telegram): honor access group allowlists

(cherry picked from commit b6ae0b83a61a1f779ee41b5d639b6049bfd422ce)

* fix(delivery): require outbound send result for success

(cherry picked from commit 372e270871a2e45be1484df57651f1a1891610bb)

* fix(agents): cap live exec update payloads

(cherry picked from commit b7d0d92600dc1c80d970ded2b587266e6776b8b0)

* fix(telegram): keep polling watchdog on getUpdates liveness (#78646)

(cherry picked from commit 440111ff6f991ff450696a3b3289d93f7899f059)

* fix(subagents): honor archiveAfterMinutes for session-mode reaping (#78263)

Merged via squash.

Prepared head SHA: b4154670087dae4a00b6ea3030e3a4f4bc6f0c73
Co-authored-by: arniesaha <3646287+arniesaha@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman

(cherry picked from commit 1c331a814a1db0eb0670378cb0edda398d664cd0)

* fix(telegram): avoid fallback after message tool send (#78726) (thanks @neeravmakwana)

* telegram: correlate message-tool sends with inbound turn (#78685)

Register the active Telegram inbound SessionKey/outbound peer while dispatching,
and mark inbound lane delivery when deliverOutbound emits a matching telegram
message:sent success. Prevents rewritten silent-reply fillers after visible
tool-routed replies with an empty final.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(telegram): track message action delivery

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
(cherry picked from commit 447182a8520beec3b15e802225debd3ba901652c)

* fix: bound stale task reload blockers

(cherry picked from commit 6009b86f0de45a53c23fd484a9efb454b0e3e8b2)

* fix(commands): audit explicit task records

(cherry picked from commit 70defcc04607ca0be293193e1f97fdeeadce0167)

* fix(anthropic): reject uppercase dynamic model ids

(cherry picked from commit f37fba8d5ac4bffc750d830c575b9c4346cda04c)

* fix(openai): honor embedding output dimensions

(cherry picked from commit ea116ca36ed3cfc0e7aa109b0eb6b47ec820d187)

* fix(cli): normalize heic model-run files

(cherry picked from commit 32c135692657fcf7372af19148027053856ca44f)

* fix(openrouter): canonicalize auto selector refs

(cherry picked from commit 610e882dbf813a5c14696771ad5f84f1026e3e13)

* fix(plugins): forward setChannelRuntime from non-bundled external setup entries (#77799)

Merged via squash.

Prepared head SHA: 7b7676be0db7a4b7f3752c38df2d95aec2fbc633
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Co-authored-by: openperf <80630709+openperf@users.noreply.github.com>
Reviewed-by: @openperf

(cherry picked from commit 42a32298f9681b6af7e8ed001401f24caefa895e)

* fix(model): repair provider replay edge cases

(cherry picked from commit 85b914a4e1863c1bcd6acba9c4fb942887969561)

* fix(gemini): gate thought-signature replay trust

(cherry picked from commit a428568157c3c27df3be9c43e6c89450ff219a46)

* fix(discord): audit voice channel permissions

(cherry picked from commit a4d720655860d5415e3a1099faaa3e5cc9ad02fd)

* fix(discord): smooth voice capture prompts

(cherry picked from commit 6e5ba8b0471f2d7e3e534a71d5bde432921f7c4f)

* fix(whatsapp): resolve outbound PN to LID via auth-dir forward mapping (#74925)

Merged via squash.

Prepared head SHA: 5f51cb7cb3c309753f5160713b787bdade55add2
Co-authored-by: edenfunf <146086744+edenfunf@users.noreply.github.com>
Co-authored-by: mcaxtr <7562095+mcaxtr@users.noreply.github.com>
Reviewed-by: @mcaxtr

(cherry picked from commit fcdfa30703b8111520b04a18e165927d564775bd)

* fix: persist rotated gateway session files

Signed-off-by: sallyom <somalley@redhat.com>
(cherry picked from commit bf2511098f79eae2c4d638c132bfd458aae26f6e)

* fix(onboard): recover externalized channel plugin from stale config (#78328)

When a user's config has a stale `channels.<id>` entry (e.g. `appId`
or tokens left over from an earlier install) and the plugin is no
longer on disk -- for instance because the externalized npm package
was uninstalled or pruned during an upgrade -- `handleChannelChoice`
used to dead-end with "<channel> plugin not available." and leave
onboard stuck until the user manually deleted the config entry and
re-ran the CLI.

Two discovery paths are affected:

1. The `installedCatalogEntry` branch: when
   `loadScopedChannelPlugin` returns null but the catalog entry still
   carries `install.npmSpec`, fall back to
   `ensureChannelSetupPluginInstalled` with the same entry so onboard
   can reinstall the plugin from the official catalog.

2. The bundled-enable `else` branch: with a non-empty
   `channels.<id>` record, `isStaticallyChannelConfigured` drops the
   channel from `installableCatalogEntries`; if the plugin is also
   missing on disk (so it never enters `manifestInstalledIds`), both
   discovery buckets come back empty and the channel falls through to
   `enableBundledPluginForSetup`. Before delegating to that bundled
   path, consult the trusted catalog via
   `getTrustedChannelPluginCatalogEntry` and, if an `install.npmSpec`
   is available, drive the same catalog install flow used by a fresh
   pick of the channel.

Both new fallbacks re-apply the `resolveConfigDisabledHint` guard
that `enableBundledPluginForSetup` has always enforced, so an
operator-disabled channel (`plugins.entries.<id>.enabled === false`
or explicit `channels.<id>.enabled === false`) with a stale config
entry cannot be silently reinstalled or re-enabled through the
catalog path.

Both branches also keep their previous behavior when no catalog npm
spec is available (e.g. purely bundled channels), so this change is
a superset of the old flow rather than a replacement.

Affects all externalized channel plugins listed in the core
package's `files` exclusion (qqbot, bluebubbles, discord, whatsapp,
line, msteams, feishu, googlechat, nostr, zalo, zalouser,
synology-chat, tlon, twitch, and similar).

(cherry picked from commit 329580c64d13657592c3fabb97ff567c2e292bb6)

* fix(whatsapp): dedupe captioned MEDIA auto-replies

(cherry picked from commit 1ede151ad0d80b6e9ae9f9767c0a9b6bc27769f1)

* docs: note whatsapp media directive dedupe

(cherry picked from commit 54abdd786d093e182dc35a18dec2fd92a4d93e90)

* fix(whatsapp): adapt media dedupe to release delivery path

* fix: reuse codex native approvals

(cherry picked from commit f1bf2a80a616642497cc6e085fa706ba612c5fbc)

* fix: scope native approval reuse by session

(cherry picked from commit a758b5e99c2a95bddbd875a9f90879fe97c7099f)

* fix: let codex guardian own native permission approvals

(cherry picked from commit fcfdf02b16798b0634901568b304ff9629f4273e)

* fix: refresh plugin approval protocol models

(cherry picked from commit a4d6378a41b6b98866b8d17e6eb270976738dba0)

* fix(btw): keep usage placeholder visible

Fixes #62877.\n\nThanks @RajvardhanPatil07.

* feat(cron): add computed status field to --json output (#78701)

* feat(cron): add computed status field to --json output

`openclaw cron list --json` and `openclaw cron show <id> --json` now
include a top-level `status` field on each job object, computed from
enabled + state.runningAtMs + state.lastRunStatus.

Values: "disabled" | "running" | "ok" | "error" | "skipped" | "idle"

This matches the human-readable status column already shown by
`cron list` and `cron show` (without --json), making it easier for
external tooling (dashboards, ops gateways) to determine job state
without re-implementing the derivation logic.

The raw state object is preserved unchanged for backward compatibility.

* fix: preserve lastStatus fallback + add changelog entry

Address ClawSweeper review findings:
- P2: Fall back to deprecated state.lastStatus when lastRunStatus is
  absent, matching the existing formatStatus behavior for legacy jobs.
- P3: Add CHANGELOG.md entry under Unreleased for this user-facing
  CLI feature.

* fix: address lint errors - add braces and avoid spread-in-map

---------

Co-authored-by: Rodin <rodin@forgedthought.ai>
Co-authored-by: claw <claw@weiker.me>

* docs(cli): document cron list/show --json status field

* Fix Tavily tool SecretRef runtime config

Resolve Tavily dedicated tool credential lookup against the active runtime config snapshot.

PR: https://github.com/openclaw/openclaw/pull/78610

* Feat/channels list show all and drop auth (#78456)

* feat(channels list): drop auth providers, add --all, surface installed/configured/enabled

`openclaw channels list` used to conflate two very different surfaces: chat
channels and OAuth/API-key auth providers for model routing. The auth
section was the first and most visible block in the output even for
operators who only cared about chat channels, and its JSON `auth` key
leaked model-provider identities into a command whose top-level help
describes it as channel management. Worse, the command silently hid
every channel that had no configured account, so users could not tell
from `channels list` which bundled or catalog channels were even
available to configure.

Split the surface cleanly around channels only:

1. Remove the `Auth providers (OAuth + API keys)` text section and the
   `auth` field from the JSON payload. Model-provider auth profiles
   remain reachable via `openclaw models auth list`, which is where
   they conceptually belong.

2. Add a `--all` flag to surface every channel an operator could
   configure: bundled channel plugins that have no account yet and
   catalog-listed external channels whose plugin package is not even
   installed on disk. Without `--all` the output still shows only
   channels with at least one configured account, matching the
   previous default behavior so existing scripts keep working. The
   "empty" default path now prints a hint pointing at `--all`.

3. Render three explicit status tags per row — `installed` /
   `not installed`, `configured` / `not configured`, `enabled` /
   `disabled` — so bundled-but-unconfigured plugins and installable
   catalog channels both render with accurate state instead of being
   invisible. Installed state comes from the same
   `isCatalogChannelInstalled` probe the setup flow uses, so it stays
   consistent with `openclaw onboard` and `channels add`.

4. JSON payload now carries an `origin` per channel (`configured`,
   `available`, `installable`) alongside `installed: boolean`, which
   lets tooling distinguish "user has set this up" from "user could
   set this up" without second-guessing.

Register `--all` on both the Commander CLI and the fast-path route-arg
parser so the flag works in both code paths, update the one routes
test that asserted the parsed args shape, and rewrite the old auth
profiles surface test as a broader `channels list` behavior spec
covering default output, `--all` output, JSON shape (no `auth`), and
the bundled-unconfigured + catalog-not-installed cases.

Docs: call out that `channels list` is chat-channel only now, mention
`--all`, and point at `openclaw models auth list` for what used to be
the auth providers block.

* fix(channels list): surface catalog channels that are installed on disk but not yet configured

The previous `--all` path filtered catalog entries with
`!installedByChannelId.get(entry.id)` before rendering them as
catalog-only rows. That assumed "catalog entry not already rendered
as a plugin row" implied "not installed", which is wrong: an external
channel plugin package can be installed on disk (`isCatalogChannelInstalled`
returns true) while the read-only channel loader still declines to
surface a plugin object for it — the loader only activates channels
that appear in user config, so a plugin that is installed but never
configured ended up in neither bucket and silently dropped out of
`channels list --all`.

Operator-facing symptom: `pnpm openclaw channels list --all` omitted
WeCom (and any other catalog channel in the same state) even though
its npm package was present on disk and its catalog entry existed,
while rendering every other uninstalled catalog channel as expected.

Fix: drop the `installed` filter from `catalogOnlyLines` so every
catalog entry that is not already represented by a plugin row is
rendered, and let the row itself carry the real installed/not-installed
tag. Two renderings now land in the catalog-only bucket:

- Not installed — rendered as `not installed, not configured, disabled`
  (installable row).
- Installed but unconfigured — rendered as `installed, not configured,
  disabled` (ready-to-configure row). The JSON `origin` for this case
  becomes `available`, matching the existing origin for bundled
  plugins that are installed but unconfigured, so downstream tooling
  sees a consistent "you could configure this now" signal regardless
  of whether the plugin came from bundled sources or from the catalog.

Regression test added under the WeCom scenario.

* refactor(channels list): drop model-provider usage surface, make the command channel-only

`openclaw channels list` used to append a model-provider usage/quota
snapshot (Anthropic, OpenRouter, OpenAI Codex, Gemini, Zai, Minimax,
etc.) under every invocation. That was a leftover from the days when
`channels list` was the only "operator overview" command; the same
data is now owned by `openclaw status` (overview) and
`openclaw models list` (per-provider), which handle timeouts, probe
errors, and output shape consistently for that class of data. Keeping
the snapshot wired into `channels list` meant:

- Every default invocation made one blocking `loadProviderUsageSummary`
  call that fanned out to every configured provider billing/auth
  endpoint, adding seconds of latency to a command that otherwise
  just reads local config.
- `channels list --no-usage` was the escape hatch, but the flag was
  itself a self-sustaining bug: it only existed because the command
  did work that did not belong to it.
- JSON consumers had an optional `usage` key whose shape was owned by
  the provider-usage module, not by the channels module, so any
  change upstream silently reshaped `channels list --json` output.
- Failed provider fetches printed provider-side errors on a command
  that never advertised itself as a provider-health surface.

Scope this PR tightens, in one move:

1. Remove `loadProviderUsageSummary` / `formatUsageReportLines` usage
   from `src/commands/channels/list.ts`. The command now only reads
   config, the read-only channel plugin registry, and the trusted
   catalog — matching its name.
2. Drop `--no-usage` from the Commander CLI registration, from the
   fast-path route-arg parser (`parseChannelsListRouteArgs`), and
   from `ChannelsListOptions`. The flag is gone, not silently
   ignored, so anyone depending on it will get a clear
   "unknown option" from Commander and from the fast-path router.
3. Drop the `usage` key from `channels list --json` payloads. Shape
   of the `chat` record and the new `origin` / `installed` tags
   introduced earlier in this branch are unchanged.
4. Print a single-line migration pointer at the bottom of the text
   output so operators who expected usage know where it went
   (`openclaw status` / `openclaw models list`). This replaces what
   used to be a block of fetched provider data with one static line,
   so it cannot fail or add latency.
5. Update `docs/cli/channels.md` troubleshooting to remove the
   `--no-usage` mention and point at the two new entry points.
6. Update tests: drop the `loadProviderUsageSummary` mock and the
   `"keeps JSON output valid when usage loading fails"` case,
   replace it with a positive assertion that `payload.usage` is
   undefined (locking in the narrower contract), and remove `usage`
   from every `channelsListCommand(...)` call to match the narrowed
   `ChannelsListOptions` type. The route-args test is updated to
   expect `{ json, all }` without `usage`.

No other command changes. `openclaw status` and `openclaw models list`
already render usage; they are the documented replacements.

Breaking-ish surface:

- CLI: `channels list --no-usage` now fails with "unknown option".
  Tooling should drop the flag — there is nothing left to opt out of.
- JSON: `channels list --json` no longer carries a top-level `usage`
  key. Tooling that read it must migrate to
  `openclaw status --json` or `openclaw models list --json`.

* fix(channels.list.test): widen isCatalogChannelInstalled mock signature to accept entry param

CI typecheck failed because the mock was declared with a zero-arg signature while one test called mockImplementation(({ entry }) => …). Tighten the generic so vitest's mock accepts the same params the real helper does.

* changelog: record channels list channel-only rework (#78456)

* changelog: credit @sliverp for channels list channel-only rework

* fix(plugins): share npm script shell env (#78887)

* feat(openai): add chat-latest model override

Add openai/chat-latest as an explicit direct API-key OpenAI model override, document the moving alias, and normalize unsupported Responses text verbosity for that model.

* fix(compaction): ignore metadata bytes in preflight pressure

Fix stale preflight compaction pressure estimation so metadata bytes before the latest usage record do not count as model-context tokens, while preserving post-usage tail pressure and the active transcript byte guard.

Fixes #78604.

* fix(active-memory): require admin scope for global toggles [AI] (#78863)

* fix: gate active-memory global writes by admin scope

* addressing claude review

* docs: add changelog entry for PR merge

* Honor owner enforcement for native commands [AI] (#78864)

* fix: honor owner enforcement for native commands

* addressing codex review

* addressing codex review

* docs: add changelog entry for PR merge

* fix: clear reset skills snapshot (#78873)

* fix(auto-reply): gate inline skill tool dispatch [AI] (#78517)

* fix: enforce tool hooks for inline skill dispatch

* addressing claude review

* addressing codex review

* addressing codex review

* fix: complete root-cause handling

* docs: add changelog entry for PR merge

* fix: preserve Codex OAuth doctor routes

* fix: handle mixed Codex OAuth PI recovery

* fix(doctor): preserve Codex route repair sequencing

* chore(release): set version to 2026.5.6

* ci(release): speed up beta publish path

(cherry picked from commit a68ad39877dd9cf2ac563b9a8a5059446576d7a0)

* chore(release): set version to 2026.5.7

* fix(plugins): type legacy peer install args

* fix(release): remove stale unused symbols

* test(discord): type voice capture stream mock

* chore(release): set beta package version

* fix(release): clear final validation blockers

* chore(release): set stable package version

* test(release): align stable onboarding npm prompt

* fix(slack): use standard Markdown in inboundFormattingHints

inboundFormattingHints() returned text_markup: 'slack_mrkdwn', but the
output pipeline runs markdownToSlackMrkdwn() which converts standard
Markdown. This caused double-conversion (bold became italic, links broke).

Fix: use text_markup: 'markdown' and instruct models to write standard
Markdown.

* feat(xgw): cross-gateway session routing, sessions_send reply, fleet config, route registration, lifecycle, and porting fixes

Conflict resolution:
- server-http.ts: included both upstream's isManagedOutgoingImagePath() and our isXgwPath(); XGW handler placed after upstream additions in dispatch order
- server.impl.ts: added initXgw() inside if(!minimalTestGateway) block; preserved upstream else branch with startupTrace.detail()

* fix: configurable XGW security prompt + relaxed default policy (#29)

- Add fleet.crossGateway.securityPrompt config option to allow
  overriding the default cross-gateway security prompt per-instance.
- Update the default prompt to allow cross-gateway agents to perform
  tasks as they would for a human user via Slack (rule 4), enabling
  trusted fleet peer interactions while retaining credential protection.
- Wire the config override into both spawnWorker and dispatchDirect.
- Add securityPrompt to XgwConfig types and Zod schema.
- Regenerate schema.base.generated.ts.

Co-authored-by: Aster (Brightfire) <aster@brightfire.net>

* feat(xgw): Ed25519 inbound auth signature verification

* fix(cost): preserve cacheWriteShort during models.json normalization

resolveModelCost() reconstructs the cost object with only the 4 base fields
(input, output, cacheRead, cacheWrite), which strips cacheWriteShort on every
gateway restart when the models.json file is re-normalized.

This preserves the optional cacheWriteShort field through normalization so
that the per-message cost correction in attempt.ts (#26) can actually read it.

Without this fix, cacheWriteShort must be manually re-added after every
gateway restart, making #24 and #26 ineffective in practice.

* feat(cost): add cache-retention-aware cost estimation (#24)

Adds cacheWriteShort to models.json cost schema and threads cacheRetention
through estimateUsageCost() so 5m-TTL cache writes (used by worker/sub-agent
sessions) are costed at the correct 1.25x rate instead of the 2x (1h) rate.

- New optional cacheWriteShort field in model cost config
- estimateUsageCost() accepts cacheRetention parameter
- All call sites updated to pass cacheRetention from agent config
- 4 new test cases covering short/long/fallback/backward-compat
- Backward compatible: missing cacheWriteShort falls back to cacheWrite

Co-authored-by: Aster (Brightfire) <aster@brightfire.net>

* refactor(cost): replace post-correction with pre-mutation for short-TTL cache write pricing

Replaces the post-correction approach from #26 with a cleaner pre-mutation
pattern. Instead of patching usage.cost after the Pi library's calculateCost()
runs, wrap the streamFn to pass a cloned model with cacheWrite set to the 5m
rate. calculateCost() then naturally computes the correct per-message cost.

This eliminates coupling to Pi library internals and follows the established
streamFn wrapper pattern used throughout the attempt loop.

* fix(context-window): fix tool-result token 2x estimate + preflight compaction early return

* fix(context-window): cap configured context window at catalog native maximum (#31)

* feat(config): add agents.defaults.sessionResetPrompt (#51586)

* feat(control-ui): configurable HTML page title

Adds gateway.controlUi.title config option. Resolution priority:
1. gateway.controlUi.title (explicit config)
2. ui.assistant.name / identity.name
3. 'OpenClaw Control' (default)

Implementation uses a stable placeholder (__OPENCLAW_CONTROL_TITLE__)
in ui/index.html (not brittle string matching), plus a client-side
document.title update from the bootstrap config JSON after JS loads.

* docs: add BRIGHTFIRE_PATCHES.md for stable/v2026.5.3

* build: regenerate base config schema after v2026.5.7 patches

* chore: bump version to 2026.5.7-bf1

* fix(config): add controlUi.title to Zod schema (strict mode fix)

The control-ui title feature added the type and runtime logic but missed
the Zod schema entry. Since controlUi uses .strict(), any config with
gateway.controlUi.title would throw ZodError at startup.

* fix(ci): add actions:read permission for scheduled live checks

The reusable workflow's prepare_docker_e2e_image job requires
actions:read (for download-artifact/upload-artifact), but the calling
workflow only granted contents/packages/pull-requests permissions.
Without actions:read, the nested job gets actions:none and fails.

* chore(fork): remove upstream GitHub App workflows

These workflows depend on the upstream OpenClaw org's GitHub Apps
(auto-response, labeler, mantis-discord-status) which require
GH_APP_PRIVATE_KEY and GH_APP_PRIVATE_KEY_FALLBACK secrets that
don't exist in our fork. Removing them eliminates failing CI
checks that are irrelevant to our internal usage.

Removed:
- .github/workflows/auto-response.yml (issue/PR auto-reply via Barnacle)
- .github/workflows/labeler.yml (auto-labeling for PRs/issues)
- .github/workflows/mantis-discord-status-reactions.yml (Discord status sync)

* Revert "chore(fork): remove upstream GitHub App workflows"

This reverts commit a62dd864947127722fffcd29df30465f8752ce08.

* chore(fork): disable 40 upstream-only workflows

Moved to .github/workflows/disabled/ so GitHub ignores them but files
remain in version control. These are upstream community management,
release pipelines, docs infrastructure, provider integration tests,
and platform-specific scans that serve no purpose in our Brightfire fork.

Disabled: auto-response, labeler, maintainer-command-reactions,
mantis-discord-*, clawsweeper-dispatch, stale, duplicate-after-merge,
docker-release, npm-release, macos-release, release-checks,
release-publish, full-release-validation, plugin-releases,
docs-sync, docs-translate, docs, docs-agent, qa-live-transports,
codeql-android/macos, ci-build/testbox, windows-testbox/blacksmith,
scheduled-live-checks, openclaw-performance, locales, live-media,
install-smoke, crabbox-hydrate, test-performance, package-acceptance,
update-migration, opengrep-full.

Kept active: ci.yml, codeql.yml, opengrep-precise.yml,
sandbox-common-smoke.yml, workflow-sanity.yml

* chore(fork): add disable-fork-workflows script for re-applying after upstream pulls

Added scripts/disable-fork-workflows.sh to re-disable upstream-only
workflows after pulling from upstream. Includes README in the disabled/
directory documenting what's disabled and why.

Kept active: ci.yml, codeql.yml, opengrep-precise.yml,
sandbox-common-smoke.yml, workflow-sanity.yml

---------

Signed-off-by: sallyom <somalley@redhat.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Co-authored-by: Penchan <5032148+p3nchan@users.noreply.github.com>
Co-authored-by: pingu <pingu@penchan.co>
Co-authored-by: mkdev11 <MkDev11@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: praveen9354 <praveen9354@gmail.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Kevin Lin <kevin@dendron.so>
Co-authored-by: Josh Lehman <josh@martian.engineering>
Co-authored-by: pashpashpash <nik@vault77.ai>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
Co-authored-by: Sarah Fortune <sarah.fortune@gmail.com>
Co-authored-by: Brandon <bzarnitz13@gmail.com>
Co-authored-by: 李claw <qq230849622@gmail.com>
Co-authored-by: 李claw <264894741+qq230849622-a11y@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>
Co-authored-by: Elliot Drel <156480527+ElliotDrel@users.noreply.github.com>
Co-authored-by: Eduardo Piva <efpiva@gmail.com>
Co-authored-by: Juan Flores <112629487+juan-flores077@users.noreply.github.com>
Co-authored-by: Kelaw - Keshav's Agent <keshavbotagent@gmail.com>
Co-authored-by: pickaxe <54486432+ProspectOre@users.noreply.github.com>
Co-authored-by: Bek <bek.akhmedov@gmail.com>
Co-authored-by: saram ali <140950904+SARAMALI15792@users.noreply.github.com>
Co-authored-by: 兰之 <lanzhi_lee@163.com>
Co-authored-by: tianguicheng <tianguicheng@xiaomi.com>
Co-authored-by: sallyom <somalley@redhat.com>
Co-authored-by: 6607changchun <84566142+6607changchun@users.noreply.github.com>
Co-authored-by: Ayu <theayuchauhan@gmail.com>
Co-authored-by: Chunyue Wang <80630709+openperf@users.noreply.github.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>
Co-authored-by: vincentkoc <25068+vincentkoc@users.noreply.github.com>
Co-authored-by: Bryce D. Greybeard <bryce.d.greybeard@gmail.com>
Co-authored-by: Val Alexander <bunsthedev@gmail.com>
Co-authored-by: Shakker <shakkerdroid@gmail.com>
Co-authored-by: adzendo <nickfelixson@adzendo.com>
Co-authored-by: Josh Avant <830519+joshavant@users.noreply.github.com>
Co-authored-by: brokemac79 <martin_cleary@yahoo.co.uk>
Co-authored-by: NVIDIAN <speedy.hpc@hotmail.com>
Co-authored-by: Arnab Saha <arniesaha@gmail.com>
Co-authored-by: Neerav Makwana <neeravmakwana@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Sliverp <38134380+sliverp@users.noreply.github.com>
Co-authored-by: Marcus Castro <mcaxtr@openclaw.ai>
Co-authored-by: Rajvardhan Patil <rajvardhanpatil7890@gmail.com>
Co-authored-by: Aaron Weiker <aaron@weiker.org>
Co-authored-by: Rodin <rodin@forgedthought.ai>
Co-authored-by: claw <claw@weiker.me>
Co-authored-by: VACInc <hixvac@gmail.com>
Co-authored-by: Alex Knight <aknight@atlassian.com>
Co-authored-by: Pavan Kumar Gondhi <pavangondhi@gmail.com>
Co-authored-by: Christof <stocker.christof@gmail.com>
Co-authored-by: Aster (Brightfire) <aster@brightfire.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands Command implementations maintainer Maintainer-authored PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant