* refactor(codex): raise app-server floor to 0.142 and drop range-compat protocol paths
* refactor(codex): model subagent mirror state as one map
* style(codex): format event-projector
* test(codex): drop unused shared-client test import
* refactor(codex): drop v1-era notification field aliases
* fix(codex): teach models to load deferred native spawn_agent via tool_search
* docs(codex): realign harness config tables
* docs(changelog): note Codex app-server protocol update
* feat(browser): direct extension→gateway relay path for remote Chrome (#53599)
Let the OpenClaw Chrome extension pair directly to a remote gateway over
wss:// with no OpenClaw node host on the browser machine — the managed-hosting
path from #53599 (extension is the only thing installed on the laptop).
- Gateway route /browser/extension registered by the browser plugin with
auth:"plugin" + no nodeCapability, so the gateway does not pre-enforce token
auth (browser WebSockets cannot send an Authorization header). The upgrade
handler self-validates the host-local relay secret from ?token=, origin-checks
chrome-extension://, resolves the extension profile, then attaches the socket
to the same ExtensionRelayBridge the loopback relay uses. All CDP synthesis,
tab-group scoping, and the in-process Playwright /cdp client are unchanged.
- `openclaw browser extension pair --gateway-url wss://host` prints a
wss://host/browser/extension#<secret> string; the path ends in /extension so
the extension's existing pairing parser accepts it with zero extension code
changes.
- relay-server: extract attachExtensionWebSocket + export requestToken /
isAllowedExtensionOrigin / EXTENSION_RELAY_MAX_PAYLOAD_BYTES so loopback and
gateway paths share one bind + one frame cap.
- runtime-lifecycle: dispose the shared gateway WebSocketServer on shutdown.
- docs: three remote topologies (same host / direct-to-gateway / via node host).
Coverage: 6 unit tests for the handler's path/503/403/404/401/attach branches.
The full extension→bridge→CDP→Chrome loop over /browser/extension was live-proven
with a real Chrome + the built extension. The real gateway upgrade→handleUpgrade
dispatch for an auth:"plugin" unprotected route is verified against core
(server-http.ts, plugins-http.ts, route-auth.ts).
* fix(browser): harden remote extension pairing
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.
Fixes rough edges in the standalone install flow (install.sh -> openclaw onboard), found and verified by running the flow in a clean container and on a clean macOS Tahoe VM:
- Provider auth setup failures (e.g. the preselected "Anthropic Claude CLI" option on a host without a Claude CLI login) no longer kill the whole wizard. The interactive wizard notes the error and returns to the provider picker; explicit --auth-choice automation still fails fast.
- Onboarding config now persists before the channel/search/skills steps, so a crash or cancel during channel pairing no longer loses auth + gateway decisions.
- With model auth skipped, finalize no longer auto-sends the "Wake up, my friend!" message (which always failed with a provider auth error). The hatch seed is gated on usable model credentials and a "Model auth missing" note explains the next step.
- Search provider picker no longer labels non-key credentials (e.g. SearXNG base URL) as "API key required".
- install.sh no longer warns "PATH missing npm global bin dir" with manual fix steps after it already persisted the export line; it reports the PATH was updated and how to reload the current shell.
- Removed the dead interactive hooks onboarding step (setupInternalHooks); quickstart enables default hooks silently.
Verified live per fix in a clean Debian/Node 24 container and on a clean macOS 26.5 Parallels VM (wizard re-prompt, SearXNG label), plus wizard/onboard test suites and tsgo:core.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Tracks per-skill usage from the skill.used diagnostic event (trusted-only
delivery, file-scoped identity), sweeps workshop-created skills daily from
gateway maintenance (active -> stale 30d -> archived 90d, pinned bypass,
restore-only unarchive, files never touched), filters archived skills from
snapshots fail-open, reports workspace-scoped overlap candidates, and adds
openclaw skills curator CLI, additive gateway methods, and a warn-only
doctor finding. Zero new config keys; SQLite/Kysely state only.
* feat(ui): rename, delete, and toggle sidebar session groups
Sidebar group headers gain a kebab + right-click menu with Rename group,
New group, and Delete group. Rename/delete enumerate every member session
(active + archived, across agents) via unbounded sessions.list queries and
patch category per session; delete keeps sessions and moves them to
Ungrouped. Stored-but-empty groups render as sections, and the sidebar
sort popover gains a persisted Group by toggle (Custom groups / None).
* test(ui): capture sidebar group management UI proof shots
* fix(ui): page session-group enumeration past the gateway's 100-row default
sessions.list caps an absent limit at SESSIONS_LIST_DEFAULT_LIMIT (100), so
the rename/delete member enumeration now walks nextOffset pages explicitly;
a silent cap would strand members in the old group on stores >100 sessions.
* chore(i18n): restore fallback-key tracking for new sidebar group strings after rebase
* chore(i18n): translate new sidebar group strings across locales