diff --git a/docs/docs_map.md b/docs/docs_map.md
index 5456f11536e..5ae113e490c 100644
--- a/docs/docs_map.md
+++ b/docs/docs_map.md
@@ -289,7 +289,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- Route: /channels/channel-routing
- Headings:
- - H1: Channels & routing
+ - H1: Channels & routing
- H2: Key terms
- H2: Outbound target prefixes
- H2: Session key shapes (examples)
@@ -1226,7 +1226,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H3: agents bindings
- H3: agents bind
- H3: agents unbind
- - H3: agents delete
+ - H3: agents delete <id>
- H2: Identity files
- H2: Set identity
- H2: Related
@@ -1418,13 +1418,13 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H1: openclaw devices
- H2: Commands
- H3: openclaw devices list
- - H3: openclaw devices remove
+ - H3: openclaw devices remove <deviceId>
- H3: openclaw devices clear --yes [--pending]
- H3: openclaw devices approve [requestId] [--latest]
- H2: Paperclip / openclawgateway first-run approval
- - H3: openclaw devices reject
- - H3: openclaw devices rotate --device --role [--scope ]
- - H3: openclaw devices revoke --device --role
+ - H3: openclaw devices reject <requestId>
+ - H3: openclaw devices rotate --device <id> --role <role> [--scope <scope...>]
+ - H3: openclaw devices revoke --device <id> --role <role>
- H2: Common options
- H2: Notes
- H2: Token drift recovery checklist
@@ -1506,7 +1506,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H3: gateway status
- H3: gateway probe
- H4: Remote over SSH (Mac app parity)
- - H3: gateway call
+ - H3: gateway call <method>
- H2: Manage the Gateway service
- H3: Install with a wrapper
- H2: Discover gateways (Bonjour)
@@ -1747,11 +1747,11 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H3: JSONL
- H3: YAML
- H2: Subcommand reference
- - H3: resolve
- - H3: find
- - H3: set
- - H3: validate
- - H3: emit
+ - H3: resolve <oc-path>
+ - H3: find <pattern>
+ - H3: set <oc-path> <value>
+ - H3: validate <oc-path>
+ - H3: emit <file>
- H2: Exit codes
- H2: Output mode
- H2: Notes
@@ -2039,12 +2039,12 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H3: wiki status
- H3: wiki doctor
- H3: wiki init
- - H3: wiki ingest
- - H3: wiki okf import
+ - H3: wiki ingest <path-or-url>
+ - H3: wiki okf import <path>
- H3: wiki compile
- H3: wiki lint
- - H3: wiki search
- - H3: wiki get
+ - H3: wiki search <query>
+ - H3: wiki get <lookup>
- H3: wiki apply
- H3: wiki bridge import
- H3: wiki unsafe-local import
@@ -4492,7 +4492,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H3: Volume (required)
- H3: Variables
- H2: Connect a channel
- - H2: Backups & migration
+ - H2: Backups & migration
- H2: Next steps
## install/raspberry-pi.md
@@ -5129,7 +5129,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- Route: /platforms/mac/voicewake
- Headings:
- - H1: Voice Wake & Push-to-Talk
+ - H1: Voice Wake & Push-to-Talk
- H2: Requirements
- H2: Modes
- H2: Runtime behavior (wake-word)
@@ -8544,7 +8544,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
- H3: 3.6 Discovery (AML.TA0008)
- H4: T-DISC-001: Tool Enumeration
- H4: T-DISC-002: Session Data Extraction
- - H3: 3.7 Collection & Exfiltration (AML.TA0009, AML.TA0010)
+ - H3: 3.7 Collection & Exfiltration (AML.TA0009, AML.TA0010)
- H4: T-EXFIL-001: Data Theft via webfetch
- H4: T-EXFIL-002: Unauthorized Message Sending
- H4: T-EXFIL-003: Credential Harvesting
diff --git a/scripts/generate-docs-map.mjs b/scripts/generate-docs-map.mjs
index 84fe3c571e8..0e591e95b0b 100644
--- a/scripts/generate-docs-map.mjs
+++ b/scripts/generate-docs-map.mjs
@@ -84,14 +84,20 @@ function stripFrontmatter(raw) {
return raw;
}
+function escapeMarkdownHtmlText(value) {
+ return value.replace(/&/gu, "&").replace(//gu, ">");
+}
+
function cleanHeadingText(value) {
- return value
+ const normalized = value
.replace(/\s+#+\s*$/u, "")
- .replace(/<[^>]+>/gu, "")
.replace(/\[([^\]]+)\]\([^)]*\)/gu, "$1")
.replace(/[*_~`]/gu, "")
.replace(/\s+/gu, " ")
.trim();
+ // Docs map is Markdown consumed by humans and agents. Escape HTML instead of
+ // trying to strip tags so malformed source headings cannot reintroduce markup.
+ return escapeMarkdownHtmlText(normalized);
}
function extractHeadings(raw) {
@@ -198,3 +204,7 @@ const isMain = process.argv[1] ? fileURLToPath(import.meta.url) === process.argv
if (isMain) {
main();
}
+
+export const testing = {
+ cleanHeadingText,
+};
diff --git a/test/scripts/generate-docs-map.test.ts b/test/scripts/generate-docs-map.test.ts
new file mode 100644
index 00000000000..504b5af0b38
--- /dev/null
+++ b/test/scripts/generate-docs-map.test.ts
@@ -0,0 +1,13 @@
+import { describe, expect, it } from "vitest";
+import { testing } from "../../scripts/generate-docs-map.mjs";
+
+describe("generate docs map", () => {
+ it("renders heading HTML as text", () => {
+ expect(testing.cleanHeadingText("`API` ")).toBe(
+ "API <script>alert(1)</script>",
+ );
+ expect(testing.cleanHeadingText("ipt>alert(1)")).toBe(
+ "<scr<script>ipt>alert(1)</script>",
+ );
+ });
+});