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 governance and publish-hygiene pass over docs/AGENTS.md and the
pages its rules cover.
- Replace every `~/Projects` operator path in docs/ with a neutral
placeholder. 38 occurrences across 13 pages, including the private
repo path `~/Projects/manager/skills`. `docs/AGENTS.md` forbids local
paths, and its own Internal Docs bullet named one.
- Record the placeholder convention in the Published Link Rules bullet
that bans local paths.
- Document the ClawHub docs source in Source Ownership: this repo holds
no `/clawhub/**` page sources even though `docs/docs.json` lists them,
so a local preview and `pnpm docs:check-links` report those routes as
missing until `OPENCLAW_DOCS_SYNC_CLAWHUB_REPO` points at a ClawHub
checkout.
- Drop the Strict-STE hard violation rate on `docs/AGENTS.md` from 18
hard (3.4 per 100 words) to 0 by splitting semicolon sentences and
sentences over 20 words, and by naming the actor in passive
sentences. No rule changes meaning.
- Convert the Maturity Scorecard paragraph to a bulleted list, matching
every other section.
- `docs/prose.md`: name v2026.8.1 as the release that removed OpenProse,
and explain the `--agent codex` flag and the third-party skills CLI.
- Link `/prose` from `tools/skills` and `tools/slash-commands`.
- `docs/docs_map.md`: correct the summary to describe the stub, and drop
the H1 that repeated the frontmatter title.
Closes audit findings: r3-0734, r3-0736, r3-0907, r3-0910, r3-2277,
r3-2278, r3-2285, r3-2286, r3-2287, r3-2288, r4-clawhub-0001
Partially addresses r3-0906 (private path removed; publish-tree
exclusion left as a follow-up). Not addressed: r3-0909 (generator
change).
* feat(approvals): standing-grant ledger, revocation, and configurable terms
Completes the operator half of cron standing grants (#129526):
- Grants are listable and revocable. New gateway methods
exec.approval.grants.list/revoke (operator.approvals scope), CLI
'openclaw approvals grants list|revoke', and a Standing grants section
on the Control UI approvals page with per-row revoke. Revocation is
idempotent, records the acting client, and takes effect at the next
occurrence's spawn boundary.
- Grant terms are frozen at mint and configurable. Default stays
until-revoked (matching what shipped Always allow has always meant);
tools.exec.grantExpiryDays sets a day-bounded default for future
grants (enterprise fleet policy), and resolve surfaces may override
per grant via grantExpiresInDays / --expires-in-days. Existing grants
keep their minted terms; config changes are never retroactive.
- expires_at_ms goes nullable (NULL = until revoked). The mandatory-
expiry shape never reached a release tag, so the lazy ensure rebuilds
it in place; grants are re-derivable authority, so the fail-closed
cost is one re-prompt.
- Approval cards say what Always allow does. Automation approvals carry
a standing-grant ApprovalScope (new union member) built server-side
from the cron run registry (now carrying the job display name); the
Control UI inbox card and modal render it via i18n, e.g. 'Always
allow runs this exact command for "grant-demo" without asking, for
10 days (revocable)'.
- Aux method registries stay in lockstep: new parity test fails when a
GATEWAY_AUX_METHODS entry lacks a lazy handler (this gap produced
live unknown-method errors during bring-up).
Live-proven on a hermetic gateway: until-revoked grant ran 62 promptless
occurrences; UI and CLI revocation each returned the prompt on the next
occurrence; config default stamped exactly 10.0 days via a UI resolve;
--expires-in-days 99 override stamped 99.0 days; ledger and card
screenshots captured from the running Control UI.
* chore(ui): annotate the scope narrowing assertion for the safety ratchet
* test(gateway): move aux-method parity check to its own suite
* fix(ci): boundary-parse UI approval scope; register grants schemas for native codegen
- The Swift/Kotlin generators discover named schemas through the
protocol schema fragments; the standing-grant scope member and the
grants list/revoke shapes were missing there, which made the Swift
generator silently drop the ApprovalScope union and broke ios-build.
Registered, regenerated, union and new struct emitted again.
- The chained-assertion lane rejects 'as unknown as' in the UI scope
parser; replaced with a real per-kind boundary parser, which is what
the rule asks for.
- The sqlite-allow-raw marker must share the line of a mid-statement
prepare() call for the Kysely guardrail; split the pragma read so the
SAFETY comment and the allow marker each sit on their own guarded
line.
* chore(ui): record startup-budget growth for the approvals scope line
The standing-grant scope renderer and grants-ledger strings ride the
boot path (~700 B gzip). Recorded via the check's --update-baseline flow
with the reason inline; well under the committed 350 KiB hard cap.
* fix(gateway): restore the channel-restart helper export dropped on main
#118157 made startGatewayChannelFromActiveRegistry module-local while
its colocated test still imports it, breaking check-test-types and the
compact shard on every merge ref. Smallest correct main heal per the
broken-CI doctrine; the test passes again.
* fix(gateway): drive channel-restart reload coverage through its exported owner
Replaces the prior export restore: #118157 made the restart helper
module-local (the dead-export scan is right that tests are not
production consumers), but left its colocated test importing it, so
main failed check-test-types either way. The test now exercises the
same preserveManualStop semantics through rollbackStoppedGatewayChannels,
the exported reload owner, and the helper stays private.
* test(ui): answer the grants ledger request in approvals-page history tests
The approvals page now loads the standing-grant ledger next to history;
a method-aware stub answers it out of band so the ordered history mocks
keep their call counts. Adds coverage for the ledger render and the
revoke round-trip.
* chore(ui): record CI-observed startup-JS baseline for the grants surface
The e2e-real-gateway lane builds the same tree ~600 B larger than checks-ui
and local builds, past the 64 B variance allowance; record the CI-observed
value so the enforcement limit stops straddling cross-lane build variance.
* fix(cli): escape standing-grant ledger fields visibly; register grants methods in inventory tests
The grant ledger's revokedBy (client display name), automation label, and
agent-authored command now go through escapeApprovalTextForTerminal like the
pending-approvals table, so hostile control characters render as visible
\u{...} escapes instead of being silently stripped by the table renderer.
Regression test fails pre-fix. Also lists exec.approval.grants.list/revoke
in the 2026.8 release-train roster, classifies the approvals grants command
group for JSON output, and fixes the stubGrants mock typing.
* refactor(infra): move exec approvals into the shared SQLite state DB
Delete the file-runtime exec-approvals store (exec-approvals.json + .lock
sidecar machinery) on both runtimes and make the reserved
exec_approvals_config singleton row canonical. Doctor owns the one-time
import with claim/verify/receipt discipline; runtime fails closed with a
doctor instruction while un-migrated legacy state exists. The wire CAS
contract, socket semantics, and gateway auth-token derivations are
unchanged. Kills the #113929 lock-contention bug class structurally and
nets around -2.9k lines.
* fix(infra): green CI gates and retire file-era exec approvals tests
Break the migration-type import cycle with a leaf contract, regenerate the
plugin-SDK API and native i18n baselines for the intentional surface change,
drop unused exports, and replace the macOS file-era approvals test suite with
SQLite-backed behavior coverage per the obsolete-internals test policy.
* chore: green max-lines ratchet, native i18n baseline, and unused-export scan
* fix(gateway): support native Windows exec approvals
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* chore: defer changelog entry to release
* test: use tracked approvals temp directories
---------
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>