Commit graph

602 commits

Author SHA1 Message Date
Peter Steinberger
5278a8f2ed
feat: share selected sessions read-only with a paired team Gateway (#136253)
* 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.
2026-09-12 13:35:17 -07:00
Peter Steinberger
01e00e442f
feat(linux): add Omarchy agents panel with desktop handoff (#145593)
* feat(linux): add Omarchy agents panel with desktop handoff

* fix(omarchy): preserve Unicode session selection after prompts
2026-09-11 22:09:06 -07:00
Peter Steinberger
f89fa78584
feat(radius): connect models with browser sign-in and native streaming (#145377)
* 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.
2026-09-11 19:29:25 -07:00
Peter Steinberger
8a32b5a4b5
feat(crabbox): add a lease-backed sandbox backend for tool-call isolation (#144454)
* 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
2026-09-11 15:16:30 -07:00
Hannes Rudolph
1685e53b06
docs: publish release notes for v2026.9.4 (#144665) 2026-09-10 23:09:00 -06:00
Vincent Koc
f486f76460
docs: close the remaining ia and ste findings (#144089)
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>
2026-09-10 22:28:26 +08:00
Vincent Koc
b0286f17be
docs: close the small audit categories (generated, governance, link, split) (#144029)
* 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>
2026-09-10 21:52:03 +08:00
Dallin Romney
1670c5a1cc
fix(docs): align locale navigation with split release tabs (#144037)
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>
2026-09-10 06:06:05 -07:00
Vincent Koc
4aacaa0ee9
docs: information-architecture fixes (nav restructure + heading structure) (#144021)
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.
2026-09-10 20:19:38 +08:00
Vincent Koc
c0b128344c
docs(gateway,concepts,install,help): fix information-architecture findings (#143977)
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.
2026-09-10 19:20:49 +08:00
Vincent Koc
3b61516187
docs: fix information-architecture findings in plugins and channels docs (#143926)
Some checks are pending
Native App Locale Refresh / Refresh native ja-JP (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ko (push) Blocked by required conditions
Native App Locale Refresh / Refresh native nl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pl (push) Blocked by required conditions
Native App Locale Refresh / Refresh native pt-BR (push) Blocked by required conditions
Native App Locale Refresh / Refresh native ru (push) Blocked by required conditions
Native App Locale Refresh / Refresh native sv (push) Blocked by required conditions
Native App Locale Refresh / Refresh native th (push) Blocked by required conditions
Native App Locale Refresh / Refresh native tr (push) Blocked by required conditions
Native App Locale Refresh / Refresh native uk (push) Blocked by required conditions
Native App Locale Refresh / Refresh native vi (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-CN (push) Blocked by required conditions
Native App Locale Refresh / Refresh native zh-TW (push) Blocked by required conditions
Native App Locale Refresh / Commit native locale refresh (push) Blocked by required conditions
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Waiting to run
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Blocked by required conditions
Plugin Init Scaffold Validation / Validate provider scaffold (push) Waiting to run
Plugin NPM Release / preview_plugins_npm (push) Waiting to run
Plugin NPM Release / Validate release publish approval (push) Blocked by required conditions
Plugin NPM Release / preview_plugin_pack (push) Blocked by required conditions
Plugin NPM Release / Preflight plugin npm package () (push) Blocked by required conditions
Plugin NPM Release / Seal prepared plugin npm release (push) Blocked by required conditions
Plugin NPM Release / Trusted publisher OIDC exchange (push) Blocked by required conditions
Plugin NPM Release / publish_plugins_npm (push) Blocked by required conditions
Plugin NPM Release / verify_plugins_npm (push) Blocked by required conditions
Vitest Cache Warm / warm (linux) (push) Waiting to run
Vitest Cache Warm / warm (macos) (push) Waiting to run
Workflow Sanity / no-tabs (push) Waiting to run
Workflow Sanity / actionlint (push) Waiting to run
Workflow Sanity / generated-doc-baselines (push) Waiting to run
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.
2026-09-10 18:22:51 +08:00
Vincent Koc
d094012956
docs: add five orphaned pages to the navigation (#143845)
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>
2026-09-10 17:01:56 +09:00
Vincent Koc
f575b7f4ef
docs(cli,tools): fix information-architecture findings in CLI and tools pages (#143775)
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.
2026-09-10 15:41:30 +09:00
Vincent Koc
a23645697f
docs: split gateway/sandboxing into a directory of child pages (#143522)
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>
2026-09-10 09:11:27 +09:00
Vincent Koc
c925c0cee4
docs: split gateway/secrets into five child pages (#143520)
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.
2026-09-10 09:07:39 +09:00
Vincent Koc
c7617e2c9a
docs(gateway): split the RPC method reference into flat sibling pages (#143515)
`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.
2026-09-10 09:01:40 +09:00
Vincent Koc
3fe8340e34
docs: split THREAT-MODEL-ATLAS threat catalog by ATLAS tactic (#143517)
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.
2026-09-10 09:01:27 +09:00
Vincent Koc
e157c6b250
docs(plugins): split the Codex harness runtime page by reader job (#143458)
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>
2026-09-10 08:21:48 +09:00
Vincent Koc
7b6916a513
docs: split gateway configuration into an index plus four pages (#143456)
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).
2026-09-10 08:05:45 +09:00
Vincent Koc
faef46e142
docs: split help/faq into 13 topic pages (#143150)
* 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...).
2026-09-09 23:40:39 +09:00
Vincent Koc
29530dcd80
docs: split cloud-workers into an index plus ten child pages (#143158)
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.
2026-09-09 23:35:43 +09:00
Vincent Koc
82b91e5409
docs(ci): split release validation into umbrella, shards, acceptance, docker, and prerelease pages (#143163)
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>
2026-09-09 23:32:44 +09:00
Vincent Koc
c473bbcbf5
docs(plugins): split SDK entry points reference into child pages (#143151)
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.
2026-09-09 23:22:56 +09:00
Vincent Koc
ff61243170
docs(gateway): split the troubleshooting runbook by symptom area (#143160)
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.
2026-09-09 23:18:48 +09:00
Vincent Koc
ccc84ac86f
docs: split database-schemas reference into seven child pages (#143152)
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.
2026-09-09 23:18:03 +09:00
Vincent Koc
82050740b5
docs(help): split the first-run FAQ into two child pages (#143148)
`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.
2026-09-09 23:12:13 +09:00
Vincent Koc
e3aa752c03
docs(nodes): split talk.md into a parent index and four child pages (#143149)
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.
2026-09-09 23:12:06 +09:00
Vincent Koc
f7a36e6e87
docs(ci): split CI scope and routing into selection, node lanes, budgets, and dispatches (#143053)
* 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.
2026-09-09 21:39:04 +09:00
Vincent Koc
49f6843cdd
docs(install): split the Docker guide into environment variables, networking, Compose operations, and sandbox (#143087)
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.
2026-09-09 21:13:20 +09:00
Vincent Koc
87ade599b6
docs(tools): split the Skill Workshop page by reader job (#143079)
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.
2026-09-09 21:04:21 +09:00
Vincent Koc
1d80616d25
docs(channels): split the Feishu page by reader job (#143085)
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.
2026-09-09 21:03:48 +09:00
Vincent Koc
873a52f8f1
docs(reference): split the session management deep dive by reader job (#143082)
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.
2026-09-09 21:03:41 +09:00
Vincent Koc
70c90c2ae4
docs(tools): split the text-to-speech page by reader job (#142992)
* 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.
2026-09-09 20:17:17 +09:00
Vincent Koc
7420d4a0ab
docs(plugins): split the voice call plugin guide into five child pages (#143055)
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.
2026-09-09 20:17:09 +09:00
Vincent Koc
d972ecf3dd
docs(concepts): split the model providers page by reader job (#143058)
docs/concepts/model-providers.md was 43,322 characters of hand-written
reference covering four distinct reader jobs. Split it into an index plus
four child pages, one per job.

Content-preserving: the four children concatenate to a byte-identical copy
of the original body (lines 12-719), proven by sha256. No prose was
rewritten, reordered, or "improved". The index retains the original lede,
the CLI examples section, and the Related section verbatim.

Anchors: all 57 pre-split ids still resolve at /concepts/model-providers.
55 are authored <a id="..." /> stubs pointing at the page that now holds
the content; cli-examples and related are still published by the index
itself. Punctuated headings that mint both an encoded and a cleaned id keep
both. Two anchors are pinned from product code and were verified explicitly:
#byteplus-international (extensions/byteplus, official-external-provider-catalog.json)
and #volcano-engine-doubao (extensions/volcengine).

The bundled provider table was kept whole (29 rows in, 29 rows out).
2026-09-09 20:12:42 +09:00
Vincent Koc
4c41c266df
docs(concepts): split active memory into nine task pages (#143057)
docs/concepts/active-memory.md was 43,229 bytes and mixed the product
setting, an advanced plugin quick start, the escalation explanation,
eligibility rules, session commands, tuning knobs, per-provider tool
recipes, a 28-row configuration table, a starter config, and
troubleshooting on one page.

The parent keeps its lede and becomes an index over
docs/concepts/active-memory/, matching the sibling split at
docs/concepts/qa-e2e-automation/. All 31 pre-split anchor ids still
resolve on the index.

Content-preserving: the nine children concatenate byte-identically to
the original body apart from eight link-target rewrites for anchors
that now live on a different page.
2026-09-09 20:12:16 +09:00
Vincent Koc
82d4e9a423
docs(automation): split the hooks page by reader job (#143041)
The page was 46,017 characters in one flat run: a quick-start tutorial, a
how-to for writing a hook, three reference blocks (HOOK.md fields, the
bundled hooks, the event catalog and context payloads), and a
troubleshooting section. It is now an index with five children, one per
reader job.

Children:

- /automation/hooks/writing-hooks - hook directory layout, the handler
  contract, reply delivery, the HOOK.md metadata fields
- /automation/hooks/configuration - the master switch and selection
  rules, per-hook entries, discovery precedence, hook packs
- /automation/hooks/bundled-hooks - the five shipped hooks and the
  behavior and options of each
- /automation/hooks/event-types - every event key with its trigger and
  wait behavior, plus the context each producer supplies
- /automation/hooks/troubleshooting - hook not discovered, not eligible,
  not executing

The index keeps the overview, "Choose the right surface", the quick start
with its eligibility and scope subsections, plugin hooks, best practices,
the CLI pointer, and Related.

Anchor strategy: per-anchor redirects are impossible because
redirectSource() rejects any source containing [?#]. All 38 pre-split IDs
computed with parseDocsDocument stay alive on the parent index: 11 remain
natively published (hooks, choose-the-right-surface, quick-start,
plugin-hooks, best-practices, cli-reference, related, and both the encoded
and cleaned forms of the two comma headings) and 27 became authored
<a id="..." /> stubs in a "Where each section moved" list, each linking to
the page that now holds the content. Three punctuated headings emit both an
encoded and a cleaned ID; every form is covered. No ID the index still
publishes itself is stubbed, so there is no duplicate authored/canonical ID
collision. A script asserted each pre-split ID resolves end to end: 38/38
pass, all 26 index-to-child fragment targets resolve, and the 6 pages
report 0 collisions.

Losslessness: the five children and the index blocks reassemble in original
order to a body that is byte-identical to the pre-split body,
sha256 4e46aef7b20e0bc73d3ad71b108e6d6e12e8d4c2a662e96d0bf2509578372ce8.
All 14 code fences are identical one-for-one on both info string and body
sha256. Words 5,316 -> 5,695 and table rows 69 -> 75; the deltas are the
five child frontmatters and ledes, the index's 5-row topic table, and the
27-entry moved list. Largest page is now 12,525 characters.

Prose was not rewritten. Six same-page fragment links inside the moved
content now point at the child holding their target, and seven inbound deep
links from other docs pages were retargeted at the children. Retargeting
the event-context link inside the "Every event has these fields" table
widened one column, so format-docs re-padded that table; the cell contents
are unchanged.

Closes audit finding: r3-0012
2026-09-09 19:53:43 +09:00
Vincent Koc
183252510f
docs(channels): split the iMessage page by reader job (#143038) 2026-09-09 19:52:18 +09:00
Vincent Koc
056d14028f
docs(install): split the updating guide into methods, automatic updates, and rollback (#142993)
docs/install/updating.md was 56,992 bytes and mixed the recommended update
how-to with alternative update methods, auto-updater internals, rollback
strategy, and failed-update triage. Move three contiguous blocks into
docs/install/updating/ and keep the parent as an index, matching the
docs/cli/update/ split already on main.

Content-preserving: the three children concatenate back to a byte-identical
copy of the original body (sha256 282f065d…). All 38 pre-split anchor ids
still resolve on the index. The children are added to RELEASE_METADATA_PATHS
so release-metadata-only CI routing is unchanged for this content.
2026-09-09 19:41:00 +09:00
Vincent Koc
aabfc3e753
docs(help): split the live testing suites page by reader job (#143042)
docs/help/testing-live.md was 46,841 characters of 17 independent live
lanes. Split it into docs/help/testing-live/ children, one per reader job,
and keep the parent as an index that still carries the safety and
credential sections plus an anchor stub for every pre-split heading id.

Content-preserving: the children are verbatim slices of the original body.

Co-authored-by: Vincent Koc <vincent@openclaw.org>
2026-09-09 19:36:37 +09:00
Vincent Koc
e3e0def245
docs(channels): split the Matrix channel page by reader job (#142996)
docs/channels/matrix.md was 52,658 bytes across 25 top-level sections.
Split it into docs/channels/matrix/ and keep the parent as an index,
matching the docs/channels/slack/ and docs/channels/discord/ splits
already on main.

Content-preserving: the children reassemble to a byte-identical copy of
the original body (sha256 256b6d14...), with 34 fences matched
one-for-one on info string and body hash and 31 table rows unchanged.

Per-anchor redirects are impossible (redirectSource() rejects any source
containing [?#]), so all 61 pre-split ids are preserved on the index: 52
as authored <a id> stubs, and 9 that the index still publishes itself.
Ids were enumerated with parseDocsDocument, which surfaces the encoded
and cleaned variants of punctuated headings and the Accordion-derived
ids that a slug approximation would miss.

Three declared repairs make up the whole prose/link diff: one directional
reference orphaned by the move ("see below"), two same-page anchors whose
targets are now on the encryption child, and one inbound deep link from
matrix-push-rules.md.

Also adds docs/channels/matrix/** to .github/labeler.yml, which otherwise
misses the children behind its file-exact glob.
2026-09-09 19:27:30 +09:00
Vincent Koc
a48a9f4cb9
docs(providers): split the Ollama page by reader job (#143004)
docs/providers/ollama.md was 50,785 characters and mixed setup, discovery,
node-local inference, vision, config recipes, web search, advanced tuning,
and troubleshooting in one document.

Split it into nine child pages under docs/providers/ollama/, keeping the
parent as an index, matching the landed docs/providers/openai split.

Children are verbatim slices of the original body: no heading-level changes,
no ledes, no rewriting. The children concatenate byte-identically to the
original body (sha256 473cd9ad9bae67842f84ba8f3da566ba82851168a9043fe2f4623a14cb016cb7).

All 57 ids the single page published still resolve on /providers/ollama:
56 as authored <a id="..." /> stubs, plus `related`, which the index still
publishes itself.

The only prose change is one intra-page link that the split orphaned:
[Configuration](#configuration) in the model-discovery section now points at
/providers/ollama/configuration.

Co-authored-by: Vincent Koc <vincent@openclaw.org>
2026-09-09 19:07:36 +09:00
Vincent Koc
ba8ba515ac
docs(cli): split the MCP command reference by reader job (#142995)
docs/cli/mcp.md was 53,513 characters covering two unrelated jobs — running
OpenClaw as an MCP server and managing OpenClaw-saved MCP server definitions —
plus transports, JSON shapes, the Control UI page, and MCP Apps. It is now a
short index over six pages, one per reader job.

The move is content-preserving: every one of the 28 heading sections is carried
across byte-identically, all 30 code fences match one-for-one on info string and
body hash, and no prose was rewritten or reordered.

All 78 pre-split anchor ids still resolve on /cli/mcp — two because the index
still publishes them, 76 as authored <a id="..." /> stubs that link to the page
now holding the content.

Two pointers that named the MCP Apps section by file path are repointed at
docs/cli/mcp/apps.md.
2026-09-09 18:54:58 +09:00
Vincent Koc
5268a2b389
docs(start): split the Why OpenClaw evidence layer and Hermes comparison (#142989)
docs/start/why-openclaw.md was 55,884 characters. The page is two things at
once: a continuous argument (the inversion, the seven properties to prove, the
short answers, standards, governance, non-claims, the hardened setup) and an
evidence layer that argument cites (six per-property deep dives and a
source-by-source Hermes Agent comparison).

This moves only the evidence layer into children and leaves the argument whole.
The parent still reads end to end; the "How OpenClaw answers" bullets, which
already served as an index with per-section anchor links, now link to the pages
that hold each answer.

Content-preserving: the seven children are exact byte slices of the previous
body. Restoring their headings and removing the added frontmatter reproduces
the original body with an identical sha256.
2026-09-09 18:54:50 +09:00
Vincent Koc
26b84d3f38
docs(tools): split the browser page by reader job (#142984)
* docs(tools): split the browser page by reader job

docs/tools/browser.md was 55,693 characters across 21 H2 sections mixing
explanation, how-to, reference, and troubleshooting. Move each section into
docs/tools/browser/ and keep /tools/browser as the index.

The split is content-preserving: the nine child pages plus the three blocks
the index still publishes (lede, What you get, Related) reconstruct the
original body byte-for-byte (sha256 a28d5ea4...). Only the four H2 lines that
became child page titles are not reproduced verbatim; each keeps its anchor
on the index.

Every one of the 43 pre-split anchor IDs -- headings, their percent-encoded
and cleaned variants, and the Accordion and Tab titles -- is authored as an
<a id> stub on the index, so existing /tools/browser#... links still resolve.
Per-anchor redirects are not possible: redirectSource() rejects sources
containing [?#].

* docs(tools): retarget cross-references orphaned by the browser split

Eleven link targets, no prose changes. Three were same-page or same-route
anchors inside the moved content: /tools/browser/setup's [Configuration] link
was genuinely broken (its target moved to the configuration page), and the
[Profiles] and [Custom Chrome MCP launch] links resolved only through the
index's anchor stub. The remaining eight are inbound deep links from other
pages, retargeted at the page that now holds the section, matching the
code-mode split precedent.

* docs(i18n): add zh-CN glossary entries for the browser child page titles

check-docs-i18n-glossary requires a source term for every changed doc label.
2026-09-09 18:48:49 +09:00
Vincent Koc
309ae03db2
docs(tools): split the Sub-agents page into an index plus seven child pages (#142999)
docs/tools/subagents.md was 54,144 characters mixing reference, how-to, and
explanation. Move each H2 block verbatim into docs/tools/subagents/ and keep
the parent as an orientation index.

Every pre-split anchor id (75 of them, including component ids minted by
Accordion, Step, and ParamField titles) is preserved as an authored stub on
the index, because redirect sources cannot carry a fragment.

Closes r3-0797.

Co-authored-by: Vincent Koc <vincent@openclaw.org>
2026-09-09 18:41:08 +09:00
Vincent Koc
03582f5c6d
docs(cli): split the oversized gateway CLI page into docs/cli/gateway/ (#143005)
docs/cli/gateway.md was 55,875 bytes of command reference, how-to steps,
explanation, and contributor benchmarks on one page (ledger r3-0120,
blocking). Split it on its existing H2 boundaries into five children, one
reader job each, and keep the parent as an index.

Content-preserving. The five children, with heading levels unchanged and
their frontmatter and ledes removed, rebuild the pre-split page byte for
byte (sha256 0efba9073cfe316e22cecf4a4c94f6a74190f3660c8e5dade0ad377e73956072).
23 code fences match one for one on info string and body hash.

Per-anchor redirects are impossible here: redirectSource() throws on any
source containing [?#]. So all 98 pre-split ids are preserved on the index
instead, 97 as authored <a id> stubs and one (`related`) still published by
the index itself. Ids were enumerated with the repo's own parseDocsDocument,
including the compatibility aliases punctuated headings emit and the
ParamField counter suffixes that shift when a document is split.

The only prose change is one directional reference the split orphaned:
"All subcommands below" no longer had its subcommands below.
2026-09-09 18:40:55 +09:00
Vincent Koc
20e0ed521c
docs(cli): split the plugins command reference by reader job (#142980)
docs/cli/plugins.md was 55,872 characters and 11 H2 sections mixing a CLI
synopsis, an authoring how-to, install-policy explanation, lifecycle
reference, diagnostics, and marketplace feed trust. It is now a short index
over six children, one per reader job:

- cli/plugins/authoring             Author, Feature scaffold, Provider scaffold
- cli/plugins/install               Install, Marketplace shorthand
- cli/plugins/list                  List, Plugin index
- cli/plugins/uninstall-and-update  Uninstall, Update
- cli/plugins/inspect-and-diagnose  Inspect, Doctor, Registry
- cli/plugins/marketplace           Marketplace

The index keeps the intro, the CardGroup, the full `## Commands` synopsis with
its trace/Nix/bundled notes, and `## Related`.

Anchor strategy: per-anchor redirects are impossible, because redirectSource()
in scripts/lib/docs-redirects.mjs throws on any source containing [?#]. Every
original anchor therefore stays alive on the parent index as an authored
<a id="..." /> stub pointing at its new home. Ids were computed with
parseDocsDocument, not a slug approximation, so the nine Accordion titles, the
two Tab titles, and the three ParamField ids are covered alongside the
headings. 34 pre-split ids: 32 stubbed, 2 (commands, related) still published
by the index itself, so no duplicate authored/canonical ID is raised. All 34
verified to resolve on /cli/plugins, and all 32 stub targets verified to
resolve on their child page. Collisions are empty on the index and on each of
the six children.

Losslessness, asserted mechanically against the pre-split file:
- index prefix + the six children (frontmatter and lede removed) + index
  suffix reassemble byte-identically, sha256
  c462b672a341344fca6dc46d623f6136f337844080b97bd469faffacb12265f8
- fences 17 -> 17, every one identical on info string and body sha256
- table rows 6 -> 14 (+8 = the new index page table)
- links: 27/27 original targets retained
- words 7,266 -> 8,023 (+757 = index page table, anchor map, child ledes)
- index 55,872 -> 8,662 chars; children 3,935-22,363 chars

No prose was rewritten and no prose exception was needed. The page had zero
intra-page anchor links and zero self-route links, and the one directional
reference the orphan check finds ("the trusted plugin id replacement above")
keeps its target on the same child page.

Closes audit findings: r3-0126, r3-1163 (partially: the accordions keep their
authored anchors and are no longer buried under a 2,065-word H2)
2026-09-09 18:23:39 +09:00
Vincent Koc
fd6fdb3b96
docs(channels): split the Telegram page by reader job (#142963)
* docs(channels): split the Telegram page by reader job

docs/channels/telegram.md was 59,197 characters and mixed a tutorial, five
how-to guides, a 3,428-word feature reference, explanation, and
troubleshooting. It is now a short index over ten child pages, matching the
shape the Slack and Discord splits already put on main.

Children under docs/channels/telegram/:

- setup.md - token, DM policy, gateway restart, first pairing, group add,
  and the BotFather privacy-mode settings
- access-control.md - DM policy, group allowlists, mention gating, and
  per-chat tool policy
- messaging.md - runtime behavior, stream previews, native commands, reply
  tags, ack reactions, and send limits
- threads-and-sessions.md - forum topic session keys, per-topic agents, and
  ACP bindings
- rich-messages.md - Bot API 10.3 rich messages, inline buttons, message
  actions, and exec approvals
- media.md - photo albums, voice and video notes, locations, venues, and
  stickers
- events.md - reaction notifications, config writes, and error reply policy
- transports.md - long polling and webhook mode
- mini-app.md - the Dashboard Mini App
- troubleshooting.md - silent groups, missing commands, rejected tokens, and
  unstable polling

Anchor strategy

Every anchor the single page published stays alive on the index. The 50 ids
were enumerated with parseDocsDocument, not a slug approximation, so both
forms of the punctuated device-pairing heading are covered
(device-pairing-commands-(device-pair-plugin) and its cleaned alias). 47 are
authored <a id="..." /> stubs that link to the page now holding the content;
the remaining 3 (configuration-reference, related, and the
high-signal-telegram-fields accordion) are still published by the index
itself, so they are not stubbed and no duplicate authored/canonical ID is
raised. parseDocsDocument reports zero collisions across all eleven pages,
and every one of the 47 stub destinations resolves on its target child.

The container heading "## Feature reference" fanned out across seven child
pages, so no single child is an honest destination for it. Its stub points at
the index's own "What each page covers" list instead.

Losslessness

- 39 fenced blocks before, 39 after; info string and body byte-identical,
  zero missing and zero extra (json5 24, bash 7, json 4, yaml 3, text 1)
- 3 table rows before, 3 after, row for row
- 820 non-blank body lines before; 819 present verbatim after. The only line
  not carried over is the container heading "## Feature reference", whose
  anchor is preserved as a stub
- prose words outside fences 6,601 -> 7,290; the +689 is the new index
  scaffolding and the ten child frontmatter blocks and ledes
- links outside fences 12 -> 69; the +57 is 47 anchor stubs plus 10 child
  index entries
- zero intra-page ](# links existed before the split and zero exist after
- 59,197 characters in one page -> 11,636 index plus 59,369 across ten
  children

docs.json gains a "Telegram" nav group in the same shape as the Slack and
Discord groups. The zh-CN glossary gains the ten new page titles;
zh-Hans-navigation.json is untouched.

Closes audit findings: r3-0041, r3-0042, r3-1043

* ci(labeler): label the Telegram docs children directory

The split adds docs/channels/telegram/, which the file-exact glob does not
match. Slack and Discord already carry the sibling docs/channels/<name>/**
entry; this brings Telegram in line so children-only PRs stay labelled.
2026-09-09 18:20:15 +09:00
Vincent Koc
70ce06a9f7
docs(channels): split the Microsoft Teams page by reader job (#142986)
`docs/channels/msteams.md` was 56,760 characters with 31 H2 and 31 H3
headings, mixing tutorial, how-to, reference, explanation, and
troubleshooting content on one page.

Split it into an index plus eight child pages under
`docs/channels/msteams/`. The move is content-preserving: the children,
with their ledes removed, reassemble byte-for-byte into the original
page body (sha256 ffa99dd878b6047a6035a1d11dcb269859c88d48730e64673f1878dd5577b449).

All 85 pre-split anchor ids still resolve on the index, 84 as authored
`<a id="..." />` stubs and `#related` because the index publishes that
heading itself.
2026-09-09 18:19:55 +09:00