* fix(infra): guard channel ingress queue parseJson against corrupted JSON
* fix(infra): fix type assertion in ingress queue test
* fix(infra): use tagged parse result and validate payload before claiming
* fix(infra): remove unnecessary non-null assertion in ingress queue test
* fix(infra): scan corrupt ingress rows in claimNext
* test(gateway): avoid typed empty mock call tuple access
* fix(infra): tombstone corrupt ingress rows on duplicate enqueue and stale recovery
Two P1 gaps: enqueue() threw on duplicate when the existing row had corrupt
payload_json, and recoverStaleClaims() silently skipped corrupt claimed rows,
leaving them invisible to recovery. Both paths now tombstone the unrecoverable
row as failed with reason "corrupt_payload" and return a proper result.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(infra): resolve lint shadow and await-thenable in recoverStaleClaims
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(channels): tombstone corrupt ingress rows
* test(channels): use explicit placeholder claim tokens
* refactor(channels): name claim token values
* refactor(channels): keep claim projection direct
* fix(channels): preserve active ingress claims
* fix(channels): make corrupt recovery policy-aware
* refactor(channels): name corrupt claim token
* fix(channels): bound corrupt ingress reconciliation
* fix(channels): paginate pending ingress by key
* refactor(telegram): return live owner check directly
* build(plugin-sdk): refresh public export budget
---------
Co-authored-by: Pick-cat <huang.ting3@xydigit.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
(cherry picked from commit a824078101)
* fix(doctor): gate cross-state-dir legacy imports behind explicit doctor opt-in
A gateway or CLI command started with OPENCLAW_STATE_DIR pointing at a
non-default directory used to import legacy files FROM the default
~/.openclaw state dir (exec-approvals.json, plugin-binding-approvals.json)
and archive the originals with a .migrated suffix. Any isolated, test, or
staging run on a host with production state silently captured and archived
the production files.
Cross-state-dir imports now run only with the new crossStateDirImports
opt-in: openclaw doctor --fix (or an interactive doctor confirm) performs
the import; the implicit CLI/gateway preflight leaves the default dir
untouched and emits a notice pointing at doctor instead.
* test(doctor): include notices in legacy-state detector mocks
(cherry picked from commit 2b3dc3042f)
Behavior: a plugin before_agent_finalize hook that never resolves could previously freeze an agent run forever after a successful compaction retry, with no errors and no recovery from a gateway restart; this was the frozen-runner mechanism behind #84777. before_agent_finalize now has the same 15s default budget as sibling modifying hooks and fails open with the original final answer, converting the freeze into a bounded delay.
Surface: plugin hook runner defaults (src/plugins/hooks.ts), docs/plugins/hooks.md.
Refs #84777.
(cherry picked from commit b2baf799b4)
Prevent LINE group allowlist policy from inheriting DM allowFrom entries, so open DMs do not broaden group access. Keep group-specific allowlists and per-group overrides as the only group admission sources, and document the scoped behavior.
Co-authored-by: pgondhi987 <pgondhi987@users.noreply.github.com>
(cherry picked from commit ffff72c43a)
* chore(release): close out 2026.6.10 on main
* chore(release): align native app metadata for 2026.6.10
* chore(release): sync Android 2026.6.10 notes
* docs(changelog): preserve 2026.6.9 history
* docs(changelog): preserve 2026.6.9 history
* fix(workboard): hide archived cards in CLI list by default
The `openclaw workboard list` CLI printed soft-archived cards, while the
`workboard_list` agent tool and the `/workboard list` command both hide
cards with `metadata.archivedAt` set unless archives are requested. Users
who archived cards still saw them in CLI output and assumed archive failed.
Filter archived cards by default in the CLI list handler and add an
`--include-archived` flag mirroring the tool's `includeArchived` option, so
all three list surfaces share one default. Docs updated to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(workboard): preserve json list archive visibility
* fix(workboard): preserve json list archive visibility
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* fix(xiaomi): correct mimo-v2.5 and mimo-v2.5-pro max output tokens to 131072
* docs(xiaomi): correct mimo-v2.5 and mimo-v2.5-pro max output tokens to 131072
Update OpenClaw ClawHub docs and user-facing copy for canonical owner-qualified skill routes.\n\nEvidence:\n- pnpm docs:list\n- pnpm test src/plugins/clawhub.test.ts src/cli/plugins-cli.install.test.ts src/gateway/server-methods/skills.clawhub.test.ts ui/src/ui/views/skills.test.ts\n- pnpm exec oxfmt --check --threads=1 docs/clawhub/cli.md docs/clawhub/publishing.md docs/cli/skills.md docs/help/faq.md docs/start/showcase.md docs/tools/creating-skills.md docs/tools/skills.md src/gateway/server-methods/skills.clawhub.test.ts src/plugins/clawhub.test.ts src/plugins/clawhub.ts ui/src/ui/views/skills.test.ts\n- git diff --check\n- exact-head hosted CI passed for 8530374388d8a73235b2ac8444b95a4a4c7d0f1c\n\nNote: repo-native scripts/pr prepare-run was attempted; local broad pnpm test was stopped after unrelated existing failures in agent/media/provider shards, while hosted exact-head CI and targeted ClawHub route/copy validation were green.
* fix(plugins): make empty-allowlist warning actionable for first-time users
* fix(plugins): make empty-allowlist warnings actionable
* fix(plugins): make empty-allowlist warnings actionable
* fix(plugins): make empty-allowlist actionable for new users
---------
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
* feat(gateway-cli): scope usage-cost by agent
The `gateway usage-cost` CLI only sent `{ days }` to the `usage.cost` RPC, so
callers could not break cost down per agent or aggregate across all agents the
way the Control UI can. Add `--agent <id>` (forwards `agentId`, scoping to one
agent) and `--all-agents` (forwards `agentScope: "all"`, aggregating every
agent). The two are mutually exclusive because the gateway honors `agentScope`
only when no `agentId` is set; passing both now errors instead of silently
dropping `--all-agents`. No flag keeps the existing default-agent behavior.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(gateway-cli): scope usage-cost by agent
---------
Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>