Remove Tasks and TaskFlow runtime, APIs, CLI, SDK surfaces and panels after the Cron, session, native execution and media completion ownership cutovers. Preserve stored rows and import provable legacy native assignments through Doctor; ambiguous ownership stays untouched with a warning.
Follows #158221, #158217, #158225, #158222, #158702 and #158776. Related: #156532. Task-specific public APIs retire immediately; retained responsibilities use their existing owners.
Maintainer-authorized administrative landing after full CI run 36312986498 attempt 2 passed on 274595e2, with subsequent actual conflicts reviewed and focused checks passing. Current PR CI preflight hits the 64 KiB changed-path metadata limit before tests (run 36335042695); its duplicate security-review status mirrors that planning failure. Review and scoped proof are recorded in the PR. Published 9.4 native import is proven; remaining native completion and 9.4 rollback witnesses are explicitly unproven.
* feat: register Telnyx as an official external provider
* docs(telnyx): acknowledge non-interactive setup risk
* fix(telnyx): pin the SDK-compatible 0.2.0 provider artifact
@telnyx/openclaw-provider@0.2.0 is built against the batched provider-catalog
SDK and loads on 2026.8.1+ hosts; 0.1.0 failed with sdk-incompatible. Pin the
npm artifact with its registry integrity, raise minHostVersion to >=2026.8.1,
drop the ClawHub pin until 0.2.0 is published there, and remove the docs warning.
* fix(telnyx): restore the ClawHub install source for 0.2.0
@telnyx/openclaw-provider@0.2.0 is now published on ClawHub under the telnyx
publisher with the same npm integrity and source commit, so the catalog can
offer both sources again. npm stays the default choice.
* test(telnyx): keep over-cap suites at their baseline line count
The line-cap ratchet (#149622) rejects growth in files already past the
max-lines cap. Move the Telnyx pin test into a vendor-pins sibling module,
and drop the CLI install and onboarding additions that re-proved what the
wecom pass-through and plugin-install-plan tests already cover.
---------
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
* feat(browser): add opt-in Lightpanda semantic profiles
* fix(browser): reject direct selectors for Lightpanda profiles
* feat(browser): add portable Lightpanda deployment and benchmarks
* docs(browser): translate lightweight browser page title
* fix(browser): verify stale targets with a valid navigation control
* feat: add selectable Code Mode executors
Default enabled Code Mode to trusted Node execution and move QuickJS into a bundled executor plugin. Preserve typed discovery, JavaScript-only execution, tool authorization, continuation ownership, and explicit legacy QuickJS selections. Add a web settings selector and document both security boundaries.
* refactor: finish Code Mode executor source cutover
Remove the retired core worker copies and regenerate config documentation for the requested QuickJS plugin. The 21 added plugin paths are standard plugin management fields; core and channel counts stay unchanged.
* refactor: narrow the Code Mode plugin contract
Keep only the executor and guest protocol exports consumed by the QuickJS plugin, budget that generic contract, and load the public plugin artifact through the existing runtime test boundary.
* refactor: align Code Mode workers with current runtime boundaries
Use the worker-side task server, keep asynchronous cleanup ownership explicit, and model the real Promise contracts in lifecycle fixtures. Regenerate the requested plugin config surface and budget the exact 35 public executor exports.
* refactor: keep executor implementation types private
* chore: regenerate code mode config baseline
* fix: satisfy Code Mode executor integration contracts
* test: cover QuickJS plugin metadata and exact settings titles
* test: retain QuickJS integration in the agent runtime suite
* test: keep Code Mode validation within lint and type-shard contracts
Bundle TypeSafe AI's Jev models as an opt-in decisionModel provider, with global and per-agent selection and the optional typesafe_evaluate tool. Keep vendor translation, fixed-endpoint transport, validation, and prepared credential consumption inside the plugin while reusing the host's decision and lifecycle contracts.
Compile fixed schemas once, reducing paired local adapter overhead by 57–79%. Preserve provider-reported probabilities, authored SecretRefs, and the existing tool configuration. A transcript CI fixture now awaits provider readiness before its unchanged status assertions.
Validation includes 107 adapter tests, 1,024 synthetic concurrent transport operations with complete cleanup, live evaluations through a built isolated Gateway, 118 source-selection tests, and clean independent P0–P2 reviews. Exact-head CI and its required gate passed on 871cf0796b.
Thanks @jalehman for the adapter, expressive schemas, optional tool, and lifecycle validation work.
Co-authored-by: Josh Lehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat: let agents apply plugin and personal themes
Add declarative plugin theme metadata, descriptive theme list/get/set/import operations, and shared profile appearance writes. Plugin additions and palette updates follow hot reload without a Gateway restart. Preserve legacy local imports, bound profile authority, and atomic concurrent preference updates.
Refs #152449.
* fix: complete theme integration and defer catalog loading
* refactor: share theme mode validation and trim startup work
* chore: shrink theme assertion allowances
* test: await the initial Android gateway handoff
* fix(gateway): settle chat waits after user cancellation
* fix(gateway): preserve upstream cancellation settlement
* test(memory): preserve real worker deadline clocks
* test(daemon): preserve distinct replacement fixture identity
* test(transcripts): await completed automatic capture startup
Observe the real startup promise before exercising next-day account ownership, and always stop the service during cleanup. This removes the provider-entry timing race while preserving the ownership assertions.
* feat(apple-fm): offer on-device inference during Mac setup
Add a macOS-only setup option backed by the native Foundation Models API.
Measure availability and context size, compile the helper during explicit
setup, and keep tool execution and validation with OpenClaw.
Cover native tool handoff, transcript continuation, constrained generation,
platform selection, setup isolation, cancellation, and packaged asset roots.
Refs #109228
* fix(apple-fm): gate setup on background context detection
Offer Apple Foundation Models only after a cancellable background probe confirms an available model with at least 8192 context tokens. Cold discovery compiles a disposable helper with installed Apple tools without installing inference or changing configuration; selection prepares the persistent helper and rechecks eligibility.
Add detected-only auth-choice visibility for classic and app-guided setup. Keep unknown, unavailable, undersized, and stale configured routes out of offered choices while preserving explicit CLI selection and existing configuration.
Validated 122 focused and native live tests, near-limit recall and over-limit rejection, built-plugin discovery, synthetic Control UI visibility and activation, runtime build, core/extension typechecks, targeted core lint, plugin lint, remaining changed-check guards, and independent P0-P2 review. Broad core lint also reports the unchanged pre-existing chat-pane-render.ts line-count violation.
* fix(onboarding): keep utility inference separate from primary models
Use the configured utility model for setup until a primary is selected, and
keep Apple Foundation Models as an optional Mac setup and utility provider.
Carry the model role through discovery, auth, activation, verification, and
recovery across CLI, Control UI, and native Mac clients. Preserve existing
primaries and exclude utility-only choices from implicit primary routing.
Retain native tool constraints and validate structured results before
publication. Keep helper repair available after updates and provide explicit
setup-state facts to the small native model.
Validation covers native Apple inference and tool replay, isolated onboarding,
provider and agent ownership, aliases, recovery, generated protocols, build,
TypeScript, lint, import cycles, and independent review. Native Mac UI tests
remain pending the separate Xcode agreement; compile-only validation passed.
* test(onboarding): drop retired activation diagnostics
* fix(onboarding): preserve setup contracts across entry points
* fix(onboarding): preserve legacy primary routes during utility setup
Preserve shipped implicit primary selection through the canonical config writer
and Doctor before recording utility-model separation. Fresh utility setup stays
without a primary. Pending or deferred legacy conversion is repaired before
provider authentication, without relaxing credential or route-change guards.
Retain dynamic catalog behavior, aliases and profiles, literal model suffixes,
agent ownership, and deliberate provider/model removals. Move unchanged setup
copy behind its existing lazy UI boundary and satisfy native formatting gates.
Validation covers canonical writer and migration regressions, setup activation,
provider effects, routing/readiness, type checks, lint, import boundaries, and
signed native Mac onboarding/recovery tests. Independent review through P2 is
clean; synthetic before/after screenshots render in the PR and originating chat.
* test(onboarding): align utility migration fixtures and wrapper closure
* feat(node-host): advertise an explicit node command allowlist
Persist exact node command selection and restrict ancillary publication and hosting. Preserve the unchanged assertion baseline under the work-order stop rule; check:changed requests removing the obsolete runtime.ts count (2 to 0).
* feat(plugin-sdk): session transcript catalog reader
Expose bounded read-only native display pages and portable attribution through the existing runtime subpath. Keep pagination scoped to the original active transcript branch and allow an explicit bounded native cursor length.
* feat(session-share): read-only OpenClaw session catalog across paired gateways
Publish explicitly selected native session groups through two paired node commands. Validate the closed wire contract, reject remote profile claims, and keep receiver identity binding opt-in and display-only.
* fix(gateway): show published session catalogs to view-scoped roles
Let publication consent satisfy catalog read visibility for roles allowed to view others, while owner-only and unprofiled callers stay hidden. Preserve published attribution without accepting a remote local-session adoption claim. Regression tests reproduce four pre-fix failures; final validation stopped at the work-order baseline gate.
* docs: session sharing across gateways
Document sessions-only node setup, explicit publication groups, receiver attribution, view-scoped catalog access, and read-only limits. Add the bundled plugin inventory and generated reference entry. Live proof runbook remains outside the repository; build and rig execution are blocked by the work-order baseline restriction.
* fix(session-share): preserve source storage and paired reconnects
Respect configured stores through listing, paging, and revocation. Keep cold listings available and bound raw transcript reads. Prefer the established paired node credential on service restart, suppress unrelated host metrics, and refresh the approved plugin configuration docs.
* refactor(gateway): separate authorized catalog reads
Keep the catalog dispatcher within its owned scope and preserve post-read role checks and sender projection. Align the rebased tests with their shared setup and imports.
* refactor(channels): simplify progress rendering ownership
Keep visibility in the compositor and remove redundant mode flags from internal layout helpers. Separate Slack attention-title formatting from native approval task identity construction, avoiding discarded hashes and task objects in Block Kit rendering.
Preserve public SDK and output contracts. Remove one duplicate test left after native start/update builder unification. Related: #145345, #140037.
* fix(ui): let the popover own initial picker focus
WebAwesome already focuses the autofocus input before the opening animation. Remove the duplicate after-show focus that stole focus from a newly opened cloud configuration card. Replace the handler-only unit expectation with a deterministic browser regression that controls the actual animation and preserves initial focus, cloud focus, and machine selection.
* feat(radius): add native model provider and browser sign-in
Support Radius organization API keys and device OAuth, discover account-visible models and tiered prices, and stream native Pi messages through the provider plugin contract. Add setup docs and meaningful auth, catalog, and tool-stream coverage. Regenerate the standard plugin config inventory for the new provider.
* refactor(radius): satisfy provider validation guards
Require captured OAuth and model requests in strict test types. Project optional stream fields directly while preserving validation of supplied values. Focused tests and independent review pass.
* fix(radius): accept live fractional OAuth polling intervals
Radius device authorization advertises interval=0.1 seconds. Accept finite positive fractional intervals and round milliseconds upward; retain expiry and timer bounds. The regression failed against the original parser and all 20 OAuth tests now pass. Live pairing reaches browser authorization.
* fix(radius): publish native model routes and resolve cold starts
Declare pi-messages in the shared API data contract and emit it from authenticated Radius catalogs before registry validation. Resolve cold-start models through the existing provider hook using the same account catalog and pinned auth profile. Remove late normalization hooks and cover real registry deserialization, schema admission, and account-scoped resolution. Live authorization and catalog discovery pass; inference reaches Radius and reports the account billing gate.
* build(radius): integrate plugin publication and documentation metadata
Document the plugin package, exclude its external dist tree from the core npm package, and update extension label routing and the exact release inventory. Regenerate the plugin inventory/reference pages and brand glossary entries. Publication/build-selection and labeler coverage tests pass.
* feat(crabbox): add a lease-backed sandbox backend for tool-call isolation
Register `agents.defaults.sandbox.backend: "crabbox"` from the existing
Crabbox plugin when `plugins.entries.crabbox.config.sandbox` is present.
The Gateway, agent loop, channels, and model credentials stay on the host;
exec, file tools, and media reads run on a box that Crabbox leases for the
sandbox scope under a fixed, scope-derived lease ID, so restarts and
sibling sessions adopt the same lease instead of allocating another.
The endpoint comes from `crabbox ssh --show-secret`; token-based providers
such as Daytona rotate the SSH user, so the inner SSH backend handle is
rebuilt once the endpoint is older than ten minutes. Everything below the
endpoint reuses the built-in SSH backend and the shared remote-shell
filesystem bridge. Recreate and prune stop the lease.
Crabbox remains the only provider owner: no per-provider plugin, no new
dependency. Not supported: the sandboxed browser and sandbox.docker.binds.
* fix(crabbox): rotate sandbox lease identity and verify recorded host keys
Fixed Crabbox lease IDs are single-use: a stopped lease leaves a terminal
tombstone, so deriving the ID from the sandbox scope broke `openclaw
sandbox recreate`. Each runtime generation now mints its own ID and the
sandbox registry carries it, so restarts adopt the live lease and recreate
provisions under a fresh one.
Crabbox connects with its own SSH client, so its per-lease known_hosts may
not hold the OpenSSH entry yet. Record the host key on first contact and
run the SSH backend with strict checking against that file instead of
disabling verification, so a later impostor cannot receive the token
carried in the SSH user.
* fix(crabbox): treat terminal fixed leases as replaceable during adoption
Crabbox reports a stopped fixed lease as "has no active create attempt; it
cannot allocate a replacement". Recognize that wording so recreate mints a
fresh lease instead of failing; unknown inspection outcomes still propagate.
* fix(crabbox): make sandbox lease lifecycle durable
Reserve runtime generations before provisioning, preserve one SSH workspace owner across credential refreshes, and retain runtime authority through deferred execution and upload admission. Keep failed provisioning and cleanup recoverable under the original lease identity and workspace.
* fix(ci): clean sandbox exports and update merge fixtures
* fix(sandbox): retain provider ownership through remote operations
Route Crabbox execution and cleanup through its current repository claim
instead of retained SSH credentials. Replay shared reservations from their
original provider workspace while preserving each caller's workspace context.
Share remote workspace, skills, filesystem, and execution staging between
static SSH and provider command transports. Publish initial workspaces with
native no-replace rename and clean read-only staging directories safely.
Validation: 190 focused tests; selected types, lint, SDK and docs checks;
registered Daytona live flow including ownership transfer and cleanup;
non-root Linux/macOS bootstrap edge proof; independent P2 review clean.
Requires the Crabbox command-ownership contract in
https://github.com/openclaw/crabbox/pull/2119, following the cleanup and TTL
repair in https://github.com/openclaw/crabbox/pull/2111.
* fix(sandbox): retain ownership of prepared execution cleanup
Two nav repairs (an orphaned reference page with a real inbound link, and
two start/ pages sitting under Help > Community), Related lists and index
cards that omitted whole top-level areas, and a plain-English pass over the
pages carrying rate findings.
Hard STE violations across the 46 measured pages: 649 -> 334 at the 25-word
cap, 767 -> 388 at 20. Every page named by a rate row is now under 1.5 at
both caps except reference/templates/AGENTS.md, refuted separately.
Co-authored-by: Vincent Koc <vincent@openclaw.org>
* docs: close small audit categories (governance, generated, link)
- ci/scheduled-workflows: date the Dependency Audit triage owner and name the routing team (r5-0143)
- AGENTS.md: link the secret placeholder conventions page from the placeholder rule (r3-2264)
- model-providers/custom-providers: align the moonshot config example with the documented example model (r3-1349)
- secretref-credential-surface: group the 114 supported targets by top-level config key (r3-2248)
- generate-plugin-inventory-doc: describe docs/plugins/reference.md as a pointer, not an index (r3-2078)
- cli/file-transfer: new CLI reference page for openclaw file-transfer (r5-0196)
* docs(cli/file-transfer): qualify the non-interactive migration error
runApprovalMigration returns after printing the no-work message when no legacy
items remain (extensions/file-transfer/src/cli.ts:58-62), before it reads
process.stdin.isTTY. The non-interactive error therefore fires only when
permissions still need review. Addresses the P3 ClawSweeper finding.
---------
Co-authored-by: Vincent Koc <vincent@openclaw.org>
Align the Simplified Chinese navigation and publisher expectations with the English Releases/Contributing split. Remove the accidental QA-channel navigation entry while preserving its page, links, and explicit hidden-docs catalog guard.
Preserves all 294 Chinese route occurrences. Independent review and exact-head CI passed; hosted logs confirm the formerly failing locale-navigation regression now passes.
Co-authored-by: Dallin Romney <dallinromney@gmail.com>
Closes the structural half of the remaining `ia` audit findings.
Navigation (docs/docs.json, nav-only: no page paths, redirects or anchors change)
- Rename the `Release & CI` tab to `Releases` and move maintainer CI, testing
and maturity docs into a new `Contributing` tab; the Help tab's Testing group
moves there too, beside `reference/test`.
- Merge the one-page Reference groups `Project` and `Contributing` into
`Project and contributing`.
- Rename three maintainer-jargon Reference groups: `Codex harness` ->
`Codex runtime reference`, `Plugin maintainer reference` -> `Plugin internals`,
`Concept internals` -> `Schemas and formatting`.
- Order `Technical reference` so the cost pages and the session pages sit
together, and land `openclaw-agent-runtime` there next to
`agent-runtime-architecture` instead of in the end-user Install tab.
- Re-file pages that sat away from their siblings: `cli/devices` ->
Tools and execution, `reference/device-models` and `platforms/mac/remote` ->
the macOS app Setup group, `web/urls` after `web/dashboard-architecture`,
`announcements/bluebubbles-imessage` -> the iMessage group, `prose` ->
Install > Maintenance > Migrating, `start/hubs` + `start/docs-directory` ->
Get started > Overview.
- Group the two retired-workspace-file migration pages under a
`Retired workspace files` sub-group and pull the orphaned
`reference/templates/TOOLS` (a live redirect target) into it.
- Add five orphaned pages to the nav: `channels/qa-channel`, `concepts/mantis`,
`concepts/mantis-slack-desktop-runbook`, `specs/codex-supervision`,
`plugins/reference/anthropic-vertex`.
- Rename Get started > `Guides` to `Setup guides and reference`.
Page structure
- automation/tasks: promote the CLI-reference and cross-system accordions to
H3 headings so they appear in the outline (anchor stubs for the two titles
whose pipes would have changed the slug).
- automation/imap: give the sender-bound-token and freshness rules their own H3.
- nodes/computer-use: collect the three troubleshooting sections, previously
split across two heading levels, under one `Troubleshooting` H2.
- cli/doctor/checks: drop the meaningless `Notes` wrapper H2 and promote its
subsections (slug-preserving level change; `#notes` kept as a stub).
- reference/test/remote-proof: `Agent default` -> `Remote proof policy for
agents`, old id stubbed.
- plugins/sdk-overview: give the session-discussion paragraph its own heading;
drop the duplicate `registerNodeHostCommand` row from the infrastructure
table, which is not an infrastructure registration.
Zero published anchor ids are lost: every touched page's id set is a strict
superset of its id set on the base commit, with no collisions. Nav page set
goes 1117 -> 1123 with nothing dropped and no duplicates. Net word count +3.
Structure-only pass over 50 open `ia` audit rows in docs/gateway/,
docs/concepts/, docs/install/ and docs/help/. No page splits, no page
moves, no URL changes.
On-page structure:
- concepts/multi-user: six H3s inside the 1,288-word per-person accounts section
- concepts/model-failover: one notices section; H2 blocks reordered to
storage -> rotation -> cooldowns -> fallback -> notices
- concepts/compaction: 'Provider checkpoints' and 'Successor transcripts'
regrouped under a new 'Provider and engine behavior' H2
- concepts/memory-builtin: 'When to use' moved after 'What it provides'
- concepts/queue: 'Scope and guarantees' split into 'Input durability' and
'Lanes and scope'
- concepts/session, concepts/session-tool: 'Further reading' merged into 'Related'
- help/debugging: sections reordered (watch mode first); 'Safety notes'
demoted to H3 under raw stream logging; Node/tsx errors beside VSCode
- help/environment: OPENCLAW_HOME moved under 'Paths and instances'
- help/testing-updates-plugins: 'On this page' section index
- gateway/logging, gateway/multi-tenant-hosting, install/backups: duplicate
body H1 removed (precedent 204971f2a9), old id kept as an <a id> stub
- install/upstash: 'Next steps'; vps.md: Upstash Box and Render cards
Navigation (docs.json), no URL changes:
- install/nix -> Runtimes; install/ansible -> Hosting > Self-hosted and local
- gateway/clients and gateway/external-apps ahead of gateway/protocol
- gateway/cli-backends, local-models, local-model-services -> new
'Models and local providers' group
- gateway/heartbeat -> Capabilities > Automation
- gateway/portals -> Web interfaces
- gateway/security/dependency-locking -> Release & CI > Release process
- concepts/typing-indicators -> Messages and delivery
- concepts/usage-tracking, concepts/timezone -> Technical reference
Anchors: 15 changed pages enumerated with parseDocsDocument before and
after. Zero ids lost, zero collisions; 11 added.
Structural-only pass over the open `ia` audit rows for docs/plugins/ and
docs/channels/. No prose was rewritten; the only content additions are
headings, one Related section, and one section index.
- channels/whatsapp: group 24 flat H2 sections under four parent H2s
(Setup, Access control, Messaging and delivery, Reactions and typing)
by demoting contiguous siblings to H3. No sections reordered.
- channels/clickclack: add a Configuration H2 so the JSON5/config-keys/
hostname references stop nesting under Quick setup, give the stray
plugin-allowlist paragraph its own H3, and add a Related section.
- channels/groups: drop the two redirect-only H2 stubs and carry their
links into Related; both old ids kept as authored anchor stubs.
- plugins/bundles: promote "MCP for embedded OpenClaw" to H2 and its
children to H3, removing the H5 depth under "Supported now".
- plugins/dependency-resolution: add eight H3s inside "Install roots".
- plugins/manifest/setup-and-auth: put the `setup` object table before
its child `setup.providers` table.
- plugins/google-meet: rename the "Notes" H2 to "Audio bridge
architecture" (old `#notes` id kept as an anchor stub) and move
"Realtime session health" under it, out of Quick start.
- plugins/sdk-overview: move the session-discussion paragraph below the
registration table it was interrupting.
- plugins/sdk-setup: fold "ClawHub publishing" into "Publishing and
installing" as an H3 and add a section index after the intro.
- plugins/codex-harness-reference: link the five unlinked config-surface
table rows to the child pages that document them.
- plugins/architecture: sidebar title "Internals" -> "Architecture".
- docs.json: order channels/groups before channels/group-messages, and
move plugins/install-overrides into the maintainer reference group.
Anchor proof: parseDocsDocument id sets before/after over all 11 changed
pages -- 0 ids lost, 0 collisions, 16 ids added.
Five pages that exist and are linked from other docs were absent from
docs.json navigation entirely, so they were reachable only by search or
by following a link:
- channels/bot-loop-protection -> Channels > Configuration
- cli/transcripts -> Reference > CLI commands > Agents, models, and sessions
- plugins/copilot -> Capabilities > Plugin guides
- providers/baseten -> Models > Providers > Chat and coding models
- security/incident-response -> Gateway & Ops > Security
Each is inserted in the position its siblings suggest (alphabetical
where the group is alphabetical) rather than appended.
Refs r3-0900 r3-0901 r3-0902 r3-0903 r3-0904
Co-authored-by: Vincent Koc <vincent@openclaw.org>
Structure-only changes: no prose is added or reworded beyond the new
heading titles themselves. Every published anchor id is preserved.
- cli/doctor/checks.md: split the 42-bullet `## Notes` list into nine
H3 groups so individual checks are addressable.
- cli/doctor/sqlite-maintenance.md: sentence-case the one Title Case H3
(slug unchanged).
- cli/mcp/registry.md: move `Saved MCP server definitions` directly after
the intro that introduces its command list; `Codex tool approvals` now
follows it.
- cli/plugins/install.md: promote the nine collapsed accordions to H3
sections (they carry scope gates, `--force`/`--pin` semantics and
install-policy rules), lift the source/locator prose above them, and
head the trailing local-path run.
- cli/plugins.md: add the body H1 used by the other CLI command pages.
- cli/update/how-updates-run.md: add per-topic H4s inside
`Restart handoff`, promote `Plugin sync details` out of
`Git checkout flow`, and head the package-manager install text that was
sitting inside the Git checkout section.
- cli/onboard.md: give the flag list its own `## Flags` heading and demote
`Additional non-interactive flags` under `Non-interactive setup`.
- cli/approvals.md: move the `openclaw exec-policy` section after
`Common options` so the page opens on the command it is titled for.
- cli/infer.md: move the "turn infer into a skill" how-to off the top of
the reference page.
- cli/index.md: file `devices` with pairing/channels to match the sidebar,
and name the `automations` alias on the cron row.
- tools/tts/field-reference.md: drop the stray H3 nested inside the Inworld
accordion (its id is kept as an authored anchor) and lift the SecretRef
paragraph out from between two accordions.
- docs.json: drop the duplicate `tools/tts` nav entry, put browser
agent-tools before troubleshooting and existing-session beside profiles,
file `cli/wiki` with memory/models and `cli/openclaw` with onboard/setup.
docs/gateway/sandboxing.md was ~42k characters. Split it into 11 child
pages under docs/gateway/sandboxing/, keeping the parent as an index.
Content-preserving: the children reassemble byte-identically to the
original body (sha256), fences match one-for-one, and no prose was
rewritten or reordered.
All 25 pre-split anchor ids still resolve on /gateway/sandboxing: 21 as
authored <a id> stubs on the index, 4 still self-published by sections
the index retains.
Also closes two path-pinned CI gaps the split itself creates:
- .github/CODEOWNERS: the secops rule for this page is file-exact, so
children would have been unowned. Added a directory rule.
- .github/labeler.yml: "docs/gateway/sandbox*.md" does not match the new
directory, so children would lose the "docker" label.
Co-authored-by: Vincent Koc <vincent@openclaw.org>
docs/gateway/secrets.md was 53,408 characters across 24 H2 sections mixing
explanation, reference, and how-to content (ledger r3-0344).
Split the body into five children under docs/gateway/secrets/ and keep the
parent as an index. Content-preserving: the five children concatenate to a
byte-identical copy of the original body (sha256 33c4527c, 51,539 chars).
All 48 pre-split anchor ids survive as authored <a id> stubs on the index,
except `related`, which the index still publishes itself.
Also adds /docs/gateway/secrets/ to CODEOWNERS so @openclaw/openclaw-secops
keeps ownership of the content that moved out from under its file-exact rule.
`docs/gateway/protocol/rpc-methods.md` was 66,129 characters, four times
the largest of its seven siblings in `docs/gateway/protocol/` and over
three times the 20,000-character split signal. About 82% of the body sat
under `## RPC method families`.
Split it into five flat siblings, matching the depth `docs/gateway/protocol/`
already uses — no `docs/gateway/protocol/rpc-methods/` directory, because
nothing in the tree is that deep:
- rpc-system-and-channels.md 10,881
- rpc-talk-config-and-agents.md 18,429
- rpc-session-control.md 20,244
- rpc-devices-nodes-and-approvals.md 7,870
- rpc-bootstrap-and-events.md 10,361
- rpc-methods.md (index) 5,240
Content-preserving: no prose was rewritten, reordered, or improved. The
five children, with heading levels restored and their authored ledes
removed, concatenate with the index's retained `## RPC method families`
intro to a byte-identical copy of the original body
(sha256 ba21736d69112a0af42dba5514055a5fff5da85a74e21c1b47463c27927fff42),
modulo exactly one enumerated link rewrite (below). Fences match one for
one on info string and body sha256, table rows are 8 before and after,
and word count only grew.
Anchors: all 23 pre-split ids, enumerated with the repo's own
`parseDocsDocument`, still resolve on the index — `rpc-method-families`
because the index still publishes it, the other 22 as authored `<a id>`
stubs that point at the child holding the content. Both the encoded and
the cleaned form of each of the three comma-bearing titles is stubbed.
0 collisions on the index and on every child.
The one link rewrite: inside Session control, `sessions.subscribe` linked
to `/gateway/protocol/rpc-methods#session-list-bootstrap`. That target is
now on `rpc-bootstrap-and-events`, so the link points there directly
rather than bouncing off the index stub.
Section 3 (the threat catalog) was 29,379 of the page's 45,871 characters
and held 22 uniformly-structured threat entries across 8 ATLAS tactics.
Split it into 8 child pages, one per tactic, and keep the index at the
old URL with the scope, trust boundaries, data flows, supply-chain
analysis, risk matrix, recommendations, and appendices unchanged.
Content-preserving: the 8 children, with heading levels restored and
ledes removed, reassemble to a byte-identical copy of section 3.
All 101 pre-split anchor ids still resolve: 41 stay self-published on the
index, and the 60 belonging to moved headings are authored <a id> stubs
in a new "Where each section moved" section.
Splits the 51,106-character docs/plugins/codex-harness-runtime.md into an
index parent plus nine child pages. Section bodies are copied byte-for-byte;
the only new prose is the child frontmatter, one lede per child, and the
"Where each section moved" map on the index.
Co-authored-by: Vincent Koc <vincent@openclaw.org>
docs/gateway/configuration.md was 53,569 bytes. Move the four long reference
sections to docs/gateway/configuration/ and keep the parent as an index,
matching the sibling shape of docs/gateway/troubleshooting/ on main.
Content-preserving: the four children reassemble byte-identically to the
original body (sha256 586b563e...), with two enumerated intra-page link
rewrites and one added index block as the only prose changes.
All 34 pre-split anchor ids still resolve on the index: 9 the index still
publishes, 25 as authored <a id> stubs (including both spellings of the
Config RPC heading's encoded/cleaned id pair).
* docs: split help/faq into 13 topic pages
docs/help/faq.md was 89,648 characters and 1,613 lines - the largest
hand-written page left in the tree. It is now a 31,704-character index:
a table of the thirteen topic pages, the triage ladder it opens with,
the two pointer sections to the first-run and models FAQs, and an
anchor-compatibility list.
Content-preserving. The thirteen children are verbatim slices cut on
H2 boundaries, so no AccordionGroup is split and no prose is rewritten,
reordered, or reformatted.
All 143 pre-split anchor ids still resolve on /help/faq: 14 are still
published by the index itself, and the other 129 are authored <a id>
stubs pointing at the page that now holds the answer. Zero id
collisions on the parent and on every child.
Matches the docs/help/testing/ and docs/help/testing-live/ split shape
already on main.
* docs: link the relocated data-locality answer from the Foundation answer
Addresses the ClawSweeper P3 finding on
docs/help/faq/what-is-openclaw.md:68. The Foundation answer said to see
"Is all data used with OpenClaw saved locally?" below; after the split
that answer is on docs/help/faq/where-things-live-on-disk.md, so the
directional reference is replaced with an explicit link to it.
This is the second and last declared prose rewrite in this PR. With both
reversed, the children still reassemble byte-identically to the original
docs/help/faq.md (sha256 fe2dd3d6...).
docs/gateway/cloud-workers.md was the largest hand-written page in the
tree. It mixed explanation, configuration how-to, RPC reference,
lifecycle internals, and troubleshooting (ledger r3-0313).
Content-preserving: every child is a byte-exact slice of the original
body with heading levels restored. Reassembling the children between
the index's retained sections reproduces the original body sha256
exactly. Fences match one-for-one on info string and body digest;
table rows are unchanged.
Boundaries are resolved from exact line text rather than pinned line
numbers, so an upstream edit to the page reslices cleanly. This
revision is rebased onto ff61243 and carries main's upload-cancellation
paragraph (9956abf) into session-lifecycle.md.
The split is partial by necessity. src/docs/cloud-workers-config.test.ts
requires docs/gateway/cloud-workers.md itself to contain at least one
schema-valid `cloudWorkers` config fence, so `## Configuration` stays on
the index at its original level, along with the orientation sections
above it. The test file is untouched and green.
All 25 pre-split heading ids survive as authored stubs on the index or
are still published by it, so existing deep links keep resolving —
including ui/src/pages/labs/labs-registry.ts, which links
/gateway/cloud-workers#desktop-interactive at runtime.
docs/ci/release-validation.md was 43,706 characters. Split it into five
children under docs/ci/release-validation/ and keep the parent as an index,
matching the docs/ci/scope-and-routing/ split already on main.
Content-preserving: the five child bodies concatenate byte-for-byte with the
original frontmatter and Related section back to the original file
(sha256 68779512a6bb5f6d24b36ff67c4d057c233f551db1f7af2d40ba690c624dbf26).
Every pre-split heading id is stubbed on the index so existing links and the
six docs.json redirects into /ci/release-validation#... keep resolving.
Co-authored-by: Vincent Koc <vincent@openclaw.org>
docs/plugins/sdk-entrypoints.md was ~40.8k characters. Split the eight
body sections into docs/plugins/sdk-entrypoints/, keeping the parent as an
index that retains the lede, Plugin shapes, Related, and MCP subprocess
runtime, and publishes an anchor map for every moved section.
Content-preserving: the extracted children reassemble byte-identically to
the original body (sha256 85426d06...). The one intra-page anchor link is
rewritten to its new target as a separate, enumerated change.
Extends TYPED_PUBLIC_CONTRACT_REFERENCE_FILES in
plugin-sdk-package-contract-guardrails.test.ts to the child pages so the
typed-public entrypoint guardrail keeps scanning the same material.
docs/gateway/troubleshooting.md was 53,843 characters across 23 flat H2
symptom sections with no index. Split into docs/gateway/troubleshooting/,
keeping the parent as an index that still carries the command ladder, the
cross-cutting post-upgrade checklist, and Related.
Content-preserving. The six children plus the four sections retained on the
index reassemble to a byte-identical copy of the original body
(sha256 0f1659659df1aa5b5db90d6bbcac68829c6c2631d058c9fa402354ebd20b3d14).
All 37 fenced blocks match one-for-one on info string and body sha256, all
13 original table rows survive, and word count only grows.
All 53 pre-split ids resolve against the new tree with zero collisions: 47
are authored <a id="..." /> stubs on the index, 6 are still published by the
index itself. Four Accordion-minted ids carry a document-wide counter that is
recomputed per file (common-signatures-1/-2/-3 and fix-options-1), so each
stub targets the child's new id rather than reusing the old one. The four
heading ids that emit both a percent-encoded and a cleaned variant keep both
stubs. All 14 anchored inbound references from other docs still resolve.
docs/reference/database-schemas.md was 90,025 bytes in a single page. Split it
into docs/reference/database-schemas/ and keep the parent as an index, matching
the docs/reference/session-management-compaction/ and
docs/reference/full-release-validation/ precedents already on main.
Content-preserving: children carry their original H2 sections verbatim at their
original heading levels. The seven child bodies reassemble byte-identically to
the original body apart from one declared orphan-reference rewrite (a "below"
that now points across a page boundary).
All 46 pre-split anchor ids are stubbed on the index so existing deep links
such as /reference/database-schemas#schema-bumps-and-older-updaters continue to
resolve.
`docs/help/faq-first-run.md` was 40,388 characters in one `## ` section
holding 52 accordions across two `<AccordionGroup>` blocks.
An `<AccordionGroup>` cannot be split across files without inventing a
second wrapper, so the only content-preserving cut is the boundary
between the two existing groups:
- `help/faq-first-run/quick-start` - install, onboarding, first-run
failures, builds, and subscription basics (group 1).
- `help/faq-first-run/providers-and-hosting` - provider auth and limits,
model choice, hardware, and where to run the Gateway (group 2).
The parent stays as an index. Every one of the 56 pre-split ids still
resolves on it: `related` is still published there, and the other 55 are
authored `<a id="...">` stubs pointing at the child that now holds the
content, matching `docs/help/testing.md`.
Content-preserving: the two child bodies, with frontmatter and ledes
removed, concatenate byte-identically to the original body
(sha256 040670d96d7a8819c40d5f6bb924cccf1e9cd48596f5c264517a388cfa773911).
No prose was rewritten, reordered, or added inside the moved content.
docs/nodes/talk.md was 40,394 characters and mixed four reader jobs:
realtime session semantics, session ownership, macOS behavior and the
Gateway relay, and per-platform client UI notes.
Content-preserving split. Four child pages carry byte-identical slices of
the original body; the index keeps the intro, the voice directives, the
`talk` configuration reference, Notes, and Related, plus a page table and
anchor stubs for every heading id that moved.
The Config section stays on the index because src/config/talk-defaults.test.ts
asserts docs/nodes/talk.md contains the silenceTimeoutMs default string that
lives in the config key table. The split is therefore partial.
* docs(ci): split CI scope and routing into selection, node lanes, budgets, and dispatches
docs/ci/scope-and-routing.md was 48,194 bytes on one page: changed-scope
detection, the Node test lane sharding and cache rules, job/concurrency
budgets and platform lanes, and manual dispatch behavior. Move four
contiguous blocks into docs/ci/scope-and-routing/ and keep the parent as an
index, matching the docs/ci/ split already on main (docs/ci.md) and the
docs/install/updating/ split.
Content-preserving: the four children concatenate back to a byte-identical
copy of the original body (sha256 fcb941adb8967620266d59711e76addaff7403050210a7d38208444a372a1a3b),
with the single bash fence and its body hash unchanged. All four pre-split
anchor ids (scope-and-routing, manual-dispatches, windows-testbox-probe,
related) still resolve on the index, so /ci#scope-and-routing, the
/ci/manual-dispatches redirect in docs/docs.json, and the docs/ci.md stub
list are unaffected.
The four routes are added to the pinned Release & CI navigation list in
test/scripts/docs-sync-publish.test.ts, and the four page titles are added
to docs/.i18n/glossary.zh-CN.json next to the existing "CI scope and
routing" entry.
* test(ci): follow the docs/ci tree when asserting CI documentation content
`documents checked extended-stable dispatch instead of a raw-SHA workflow ref`
reads docs/ci.md plus a flat `readdirSync("docs/ci")`, filtered to names ending
in `.md`. That filter drops directories, so pages split into
`docs/ci/<page>/` were never read and content moved into a child looked
deleted. Walk the tree recursively instead, which is what the assertion's own
comment already says it wants: follow the content, not a single file path.
Without this, splitting docs/ci/scope-and-routing.md fails the assertion on
`VALIDATION_SHA="<full-commit-sha>"`, which moved verbatim into
docs/ci/scope-and-routing/manual-dispatches.md.
docs/install/docker.md was 41,702 bytes and mixed the container setup how-to
with an environment-variable reference, networking/provider/storage guidance,
the Compose command reference that replaced ClawDock, and the agent sandbox
plus troubleshooting accordions. Move four contiguous blocks into
docs/install/docker/ and keep the parent as an index, matching the
docs/install/updating/ split already on main.
Content-preserving: the raw extraction (cut plus heading promotion) reassembles
byte-identically to the original body (sha256 62fd3d7c93…). All 44 pre-split
anchor ids still resolve, 30 of them as authored stubs on the index, with zero
id collisions on the parent or any child. The only substantive edit inside
moved content is one intra-page link whose target moved to a sibling child; the
repo formatter re-padded that table's column in consequence.
src/dockerfile.test.ts reads docs/install/docker.md as a single file and
asserts literal strings from "Manual flow", "Source-built images with selected
plugins", "Observability", and "Health checks", so those sections stay on the
index at their original heading level and the test is unchanged and green.
The page had grown to 42,319 characters across 18 H2 sections, mixing
explanation, how-to, and reference material (ledger r3-0806).
Move each section verbatim into docs/tools/skill-workshop/ and keep
/tools/skill-workshop as an index. The extraction is byte-identical: the
eight children reassemble to the exact original body (sha256
0b344793caed30585901e7bd843922be2a699c4c9e35825d16482d33a76281db).
All 22 pre-split heading ids keep an authored <a id="..." /> stub on the
index that points at the section's new home, so links such as
/tools/skill-workshop#collection-review still resolve. #related stays
self-published by the index.
Five link rewrites are the entire non-index prose diff: one intra-page
anchor whose target moved to another child, and four directional
references ("described above" / "described below") whose targets are now
on a different page.
docs/channels/feishu.md was 42,459 characters across 47 headings, mixing a
quick start, access-control examples, a 53-row configuration reference, and a
full dynamic-agent feature guide on one page (ledger r3-0052, r3-0054, r3-1057).
Split it into docs/channels/feishu/ children, matching the sibling shape
already on main for slack/, discord/, telegram/, msteams/, matrix/ and
imessage/. The parent stays an index and keeps the two smallest
high-traffic sections (Common commands, Related) that every reader lands on.
Content-preserving: each child is a verbatim contiguous slice of the original
body. Reassembling the children plus the index-retained blocks reproduces the
original body byte-for-byte (sha256 2da7a1fd...), once the two intra-page
anchor links whose targets moved to another child are reverted. Those two
link rewrites are the entire prose diff.
All 54 pre-split anchor ids that left the index are republished there as
authored <a id="..."/> stubs pointing at their new home; common-commands and
related stay canonical on the index. 24 fences and 97 table rows preserved.
Also adds docs/channels/feishu/** to .github/labeler.yml, which the split
would otherwise leave unmatched, and registers the children in docs.json
navigation and the zh-CN glossary.
The single page was 44,159 characters and 18 H2 sections mixing on-disk
reference, a disk-budget maintenance procedure, a downgrade runbook, four
key/default tables, compaction explanation, and a troubleshooting
checklist. It is now a short index over five child pages, one per reader
job, so a reader can finish one lookup on one page.
Children under docs/reference/session-management-compaction/:
- store.md - the two persistence layers and the per-agent on-disk paths
- maintenance.md - session.maintenance keys, the disk-budget cleanup
tiers, cron run retention, and downgrading after the SQLite flip
- schema.md - sessionKey patterns, sessionId lifecycle, SessionEntry
fields, and the transcript event stream
- compaction.md - what compaction is, when auto-compaction runs, its
settings, pluggable providers, and its user-visible surfaces
- housekeeping.md - the NO_REPLY silent-turn contract and the
pre-compaction memory flush
The index keeps the original lede, the Troubleshooting checklist, and
Related verbatim: the checklist is cross-cutting (its five bullets route
to four different children), so it belongs on the router.
Anchor strategy: per-anchor redirects are impossible (redirectSource()
throws on any source containing [?#]), so all 24 heading ids from the
previous single-page version stay alive on the index. 22 are authored
<a id="..." /> stubs linking to the child that now holds the content; the
remaining two (troubleshooting-checklist, related) are still published by
the index itself and are deliberately not stubbed, which would be a
duplicate authored/canonical id. Ids were computed with
parseDocsDocument, not a slug approximation. Four punctuated headings
each mint an encoded and a cleaned id (for example
compaction%3A-what-it-is and compaction-what-it-is); both members of every
pair are stubbed. Collisions are empty on the index and all five children,
and all 18 stub link targets resolve on their child.
Losslessness: the page has no intra-page ](#...) links, so no link
rewrites were needed and the split is byte-identical with no exceptions.
The shipped index lede + the five child bodies + the shipped
Troubleshooting and Related sections, concatenated in original order,
reproduce the previous body exactly:
sha256 1ee73287c171a5af95d4b50867bc035d54dd5e4b8039418780726fa113d33d14
(43,778 chars in, 43,778 out). 3 code fences in, 3 out, matching
one-for-one on info string and body sha256 (ee97c8dc34752b81,
2425950a4be6c02b, 30578e99ae85a0e4), so every command and config example
is character-identical. Table rows 22 -> 29 (+7 is the new routing
table). Body words 5,708 -> 5,999; the entire increase is index
scaffolding. The prose diff is empty: check-orphan-refs.py flags four
directional references, and all four are fine - three have same-page
antecedents ("the maintenance owner above", "the flush logic above") and
two are numeric comparisons ("above the cap", "below the compaction
threshold"), so none was rewritten.
docs.json gains a nested group following the reference/full-release-validation
precedent, which is the sibling split actually on main.
zh-Hans-navigation.json needs no change; it is a label overlay cloned
from the English nav. The zh-CN glossary needed five new sources for the
new child titles, inserted next to the existing "Session management deep
dive" entry rather than appended, so concurrent splits touch different
regions of the file.
Closes audit finding r3-0707; also addresses r3-2221.
* docs(tools): split the text-to-speech page by reader job
docs/tools/tts.md was 52,867 characters. Split it into
docs/tools/tts/ with seven children, one per reader job, and keep
the parent as an index.
The split is content-preserving: every child body is a verbatim
contiguous slice of the original, at unchanged heading levels. The
only prose change is two in-page anchors that now point across pages.
All 156 pre-split anchor ids resolve on the index, either because the
index still publishes the heading or through an authored <a id> stub.
Nine accordion ids lost a "-1" suffix once the tab that shared their
slug moved to another page; their old ids are stubbed and redirected.
* docs(i18n): keep the TTS glossary entries beside their parent term
Appending to the end of the array collides with every other concurrent docs
PR on the same line. Placing these seven beside the existing "Text to speech"
entry puts them in a region nothing else is editing, so rebases apply cleanly.
The page had grown to 46,864 characters mixing a tutorial, a config
reference, realtime/streaming explanation, CLI/tool/RPC reference, and
troubleshooting. Keep the quick start on the index and move the rest to
docs/plugins/voice-call/ children, matching the docs/plugins/google-meet/
split already on main.
Content-preserving: the child bodies plus the retained index sections
reconstruct the original body byte-for-byte apart from three declared
cross-file anchor retargets and the table realignment the docs formatter
applies to the config reference table.
All 52 pre-split anchor ids still resolve on the index: 8 are still
published by the index itself, 44 are authored <a id> stubs.