From caa262a4c54c565d8f32753ded373d061df53db2 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Wed, 13 May 2026 18:46:05 -0300 Subject: [PATCH] feat(docs): add YAML frontmatter to all docs (title/version/lastUpdated) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every .md under docs/{architecture,guides,reference,frameworks,routing, security,compression,ops,diagrams} plus docs/README.md now opens with: --- title: "" version: 3.8.0 lastUpdated: 2026-05-13 --- 46 files updated (no docs were skipped — none had pre-existing frontmatter). [slug]/page.tsx already reads frontmatter.version and frontmatter.lastUpdated via gray-matter and renders a "v3.8.0" pill plus a "Last updated" caption, so the UI picks these up automatically. Helper: scripts/docs/add-frontmatter.mjs — idempotent (skips files that already start with `---`), falls back to a humanized basename when no leading H1 exists. Excludes docs/i18n/, docs/screenshots/, docs/superpowers/, docs/diagrams/exported/. Re-runnable safely. Also regenerated src/app/docs/lib/docs-auto-generated.ts: 44 docs across 8 sections (Architecture / Guides / Reference / Frameworks / Routing / Security / Compression / Ops), which now includes the 14 docs that were missing from the v3.7 sidebar (Cloud Agents, Guardrails, Memory, Skills, Webhooks, Evals, Authz, Agent Protocols, Repository Map, Provider Reference, Reasoning Replay, Stealth Guide, Tunnels Guide, Electron Guide). Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/README.md | 6 + docs/architecture/ARCHITECTURE.md | 6 + docs/architecture/AUTHZ_GUIDE.md | 6 + docs/architecture/CODEBASE_DOCUMENTATION.md | 6 + docs/architecture/REPOSITORY_MAP.md | 6 + docs/architecture/RESILIENCE_GUIDE.md | 6 + docs/compression/COMPRESSION_ENGINES.md | 6 + docs/compression/COMPRESSION_GUIDE.md | 6 + .../compression/COMPRESSION_LANGUAGE_PACKS.md | 6 + docs/compression/COMPRESSION_RULES_FORMAT.md | 6 + docs/compression/RTK_COMPRESSION.md | 6 + docs/diagrams/README.md | 6 + docs/frameworks/A2A-SERVER.md | 6 + docs/frameworks/AGENT_PROTOCOLS_GUIDE.md | 6 + docs/frameworks/CLOUD_AGENT.md | 6 + docs/frameworks/EVALS.md | 6 + docs/frameworks/MCP-SERVER.md | 6 + docs/frameworks/MEMORY.md | 6 + docs/frameworks/SKILLS.md | 6 + docs/frameworks/WEBHOOKS.md | 6 + docs/guides/DOCKER_GUIDE.md | 6 + docs/guides/ELECTRON_GUIDE.md | 6 + docs/guides/FEATURES.md | 6 + docs/guides/I18N.md | 6 + docs/guides/PWA_GUIDE.md | 6 + docs/guides/SETUP_GUIDE.md | 6 + docs/guides/TERMUX_GUIDE.md | 6 + docs/guides/TROUBLESHOOTING.md | 6 + docs/guides/UNINSTALL.md | 6 + docs/guides/USER_GUIDE.md | 6 + docs/ops/COVERAGE_PLAN.md | 6 + docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md | 6 + docs/ops/PROXY_GUIDE.md | 6 + docs/ops/RELEASE_CHECKLIST.md | 6 + docs/ops/TUNNELS_GUIDE.md | 6 + docs/ops/VM_DEPLOYMENT_GUIDE.md | 6 + docs/reference/API_REFERENCE.md | 6 + docs/reference/CLI-TOOLS.md | 6 + docs/reference/ENVIRONMENT.md | 6 + docs/reference/FREE_TIERS.md | 6 + docs/reference/PROVIDER_REFERENCE.md | 6 + docs/routing/AUTO-COMBO.md | 6 + docs/routing/REASONING_REPLAY.md | 6 + docs/security/COMPLIANCE.md | 6 + docs/security/GUARDRAILS.md | 6 + docs/security/STEALTH_GUIDE.md | 6 + scripts/docs/add-frontmatter.mjs | 148 ++++++++++++++++++ src/app/docs/lib/docs-auto-generated.ts | 26 +-- 48 files changed, 437 insertions(+), 13 deletions(-) create mode 100644 scripts/docs/add-frontmatter.mjs diff --git a/docs/README.md b/docs/README.md index 9ad7f89490..35218d9ccc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute Documentation" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute Documentation Navigable index of the OmniRoute documentation set. Topics are grouped by intent so you can find what you need quickly. diff --git a/docs/architecture/ARCHITECTURE.md b/docs/architecture/ARCHITECTURE.md index b80e5914e9..f5f58b52f9 100644 --- a/docs/architecture/ARCHITECTURE.md +++ b/docs/architecture/ARCHITECTURE.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute Architecture" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute Architecture 🌐 **Languages:** 🇺🇸 [English](./ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md) | 🇨🇿 [Čeština](i18n/cs/ARCHITECTURE.md) diff --git a/docs/architecture/AUTHZ_GUIDE.md b/docs/architecture/AUTHZ_GUIDE.md index 51aa328fce..588364948e 100644 --- a/docs/architecture/AUTHZ_GUIDE.md +++ b/docs/architecture/AUTHZ_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Authorization Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Authorization Guide > **Source of truth:** `src/server/authz/`, `src/shared/constants/publicApiRoutes.ts`, `src/lib/api/requireManagementAuth.ts`, `src/shared/utils/apiAuth.ts` diff --git a/docs/architecture/CODEBASE_DOCUMENTATION.md b/docs/architecture/CODEBASE_DOCUMENTATION.md index 2b0527e805..6d4f69e948 100644 --- a/docs/architecture/CODEBASE_DOCUMENTATION.md +++ b/docs/architecture/CODEBASE_DOCUMENTATION.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute Codebase Documentation" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute Codebase Documentation > **Version:** v3.8.0 diff --git a/docs/architecture/REPOSITORY_MAP.md b/docs/architecture/REPOSITORY_MAP.md index 532936cdcd..205396b9b0 100644 --- a/docs/architecture/REPOSITORY_MAP.md +++ b/docs/architecture/REPOSITORY_MAP.md @@ -1,3 +1,9 @@ +--- +title: "Repository Map" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Repository Map > **One-line description for every directory and root file.** diff --git a/docs/architecture/RESILIENCE_GUIDE.md b/docs/architecture/RESILIENCE_GUIDE.md index 06b2893d7a..8561b9e179 100644 --- a/docs/architecture/RESILIENCE_GUIDE.md +++ b/docs/architecture/RESILIENCE_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Resilience Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Resilience Guide OmniRoute has three distinct but related resilience mechanisms. Each has a different scope and purpose. Keep them separate when debugging routing behavior. diff --git a/docs/compression/COMPRESSION_ENGINES.md b/docs/compression/COMPRESSION_ENGINES.md index a5703e3e5c..5dcdaa75b4 100644 --- a/docs/compression/COMPRESSION_ENGINES.md +++ b/docs/compression/COMPRESSION_ENGINES.md @@ -1,3 +1,9 @@ +--- +title: "Compression Engines" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Compression Engines OmniRoute compression is built around engine contracts. A mode can run one engine directly diff --git a/docs/compression/COMPRESSION_GUIDE.md b/docs/compression/COMPRESSION_GUIDE.md index a602832f92..12da9d2910 100644 --- a/docs/compression/COMPRESSION_GUIDE.md +++ b/docs/compression/COMPRESSION_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "🗜️ Prompt Compression Guide — OmniRoute" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # 🗜️ Prompt Compression Guide — OmniRoute > Save 15-95% on eligible context automatically. For a quick overview, see the [README Compression section](../README.md#%EF%B8%8F-prompt-compression--save-15-95-eligible-tokens-automatically). diff --git a/docs/compression/COMPRESSION_LANGUAGE_PACKS.md b/docs/compression/COMPRESSION_LANGUAGE_PACKS.md index 73bb21339d..a5f1924db5 100644 --- a/docs/compression/COMPRESSION_LANGUAGE_PACKS.md +++ b/docs/compression/COMPRESSION_LANGUAGE_PACKS.md @@ -1,3 +1,9 @@ +--- +title: "Compression Language Packs" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Compression Language Packs Caveman compression can load language-specific rule packs in addition to the built-in English rules. diff --git a/docs/compression/COMPRESSION_RULES_FORMAT.md b/docs/compression/COMPRESSION_RULES_FORMAT.md index ad5931aff1..6cd37f52f5 100644 --- a/docs/compression/COMPRESSION_RULES_FORMAT.md +++ b/docs/compression/COMPRESSION_RULES_FORMAT.md @@ -1,3 +1,9 @@ +--- +title: "Compression Rules Format" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Compression Rules Format Compression rules are JSON files loaded at runtime. They are intentionally data-only so new diff --git a/docs/compression/RTK_COMPRESSION.md b/docs/compression/RTK_COMPRESSION.md index 0b9437abbd..43df17ecdf 100644 --- a/docs/compression/RTK_COMPRESSION.md +++ b/docs/compression/RTK_COMPRESSION.md @@ -1,3 +1,9 @@ +--- +title: "RTK Compression" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # RTK Compression RTK compression is OmniRoute's command-aware compression engine for terminal and tool output. It is diff --git a/docs/diagrams/README.md b/docs/diagrams/README.md index 31829d168a..3ae2bc003b 100644 --- a/docs/diagrams/README.md +++ b/docs/diagrams/README.md @@ -1,3 +1,9 @@ +--- +title: "Diagrams" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Diagrams Mermaid sources (`.mmd`) and exported SVGs for OmniRoute v3.8.0 architecture flows. diff --git a/docs/frameworks/A2A-SERVER.md b/docs/frameworks/A2A-SERVER.md index dd5c34f834..b814c6f35c 100644 --- a/docs/frameworks/A2A-SERVER.md +++ b/docs/frameworks/A2A-SERVER.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute A2A Server Documentation" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute A2A Server Documentation > Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent diff --git a/docs/frameworks/AGENT_PROTOCOLS_GUIDE.md b/docs/frameworks/AGENT_PROTOCOLS_GUIDE.md index 80be7a642b..15ac69679c 100644 --- a/docs/frameworks/AGENT_PROTOCOLS_GUIDE.md +++ b/docs/frameworks/AGENT_PROTOCOLS_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Agent Protocols Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Agent Protocols Guide > **Source:** `src/lib/{a2a,acp,cloudAgent}/`, `src/app/api/{a2a,acp,cloud}/`, `src/app/api/v1/agents/` diff --git a/docs/frameworks/CLOUD_AGENT.md b/docs/frameworks/CLOUD_AGENT.md index 22173d4fd6..c80c604771 100644 --- a/docs/frameworks/CLOUD_AGENT.md +++ b/docs/frameworks/CLOUD_AGENT.md @@ -1,3 +1,9 @@ +--- +title: "Cloud Agents" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Cloud Agents > **Source of truth:** `src/lib/cloudAgent/` and `src/app/api/v1/agents/tasks/` diff --git a/docs/frameworks/EVALS.md b/docs/frameworks/EVALS.md index d60e0b52b9..01dde15b56 100644 --- a/docs/frameworks/EVALS.md +++ b/docs/frameworks/EVALS.md @@ -1,3 +1,9 @@ +--- +title: "Evaluations (Evals)" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Evaluations (Evals) > **Source of truth:** `src/lib/evals/`, `src/lib/db/evals.ts`, `src/app/api/evals/` diff --git a/docs/frameworks/MCP-SERVER.md b/docs/frameworks/MCP-SERVER.md index 1796cbdc27..176f7d755b 100644 --- a/docs/frameworks/MCP-SERVER.md +++ b/docs/frameworks/MCP-SERVER.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute MCP Server Documentation" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute MCP Server Documentation > Model Context Protocol server with 37 tools across routing, cache, compression, memory, skills, and proxy operations. diff --git a/docs/frameworks/MEMORY.md b/docs/frameworks/MEMORY.md index 9aaa74f051..a3d1da4603 100644 --- a/docs/frameworks/MEMORY.md +++ b/docs/frameworks/MEMORY.md @@ -1,3 +1,9 @@ +--- +title: "Memory System" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Memory System > **Source of truth:** `src/lib/memory/` and `src/app/api/memory/` diff --git a/docs/frameworks/SKILLS.md b/docs/frameworks/SKILLS.md index b90ce4f77d..37f8d85628 100644 --- a/docs/frameworks/SKILLS.md +++ b/docs/frameworks/SKILLS.md @@ -1,3 +1,9 @@ +--- +title: "Skills Framework" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Skills Framework > **Source of truth:** `src/lib/skills/` and `src/app/api/skills/` diff --git a/docs/frameworks/WEBHOOKS.md b/docs/frameworks/WEBHOOKS.md index 066e9f6623..a39b906929 100644 --- a/docs/frameworks/WEBHOOKS.md +++ b/docs/frameworks/WEBHOOKS.md @@ -1,3 +1,9 @@ +--- +title: "Webhooks" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Webhooks > **Source of truth:** `src/lib/webhookDispatcher.ts`, `src/lib/db/webhooks.ts`, `src/app/api/webhooks/` diff --git a/docs/guides/DOCKER_GUIDE.md b/docs/guides/DOCKER_GUIDE.md index 01d59b1897..913b583725 100644 --- a/docs/guides/DOCKER_GUIDE.md +++ b/docs/guides/DOCKER_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "🐳 Docker Guide — OmniRoute" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # 🐳 Docker Guide — OmniRoute > Complete Docker deployment reference. For a quick start, see the [README Docker section](../README.md#-docker). diff --git a/docs/guides/ELECTRON_GUIDE.md b/docs/guides/ELECTRON_GUIDE.md index 7da196f30a..b6af20f64b 100644 --- a/docs/guides/ELECTRON_GUIDE.md +++ b/docs/guides/ELECTRON_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Electron Desktop Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Electron Desktop Guide > **Source of truth:** `electron/` workspace diff --git a/docs/guides/FEATURES.md b/docs/guides/FEATURES.md index d95302e886..574fcc53fa 100644 --- a/docs/guides/FEATURES.md +++ b/docs/guides/FEATURES.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute — Dashboard Features Gallery" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute — Dashboard Features Gallery 🌐 **Main README translations:** 🇺🇸 [English](../README.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/README.md) | 🇪🇸 [Español](i18n/es/README.md) | 🇫🇷 [Français](i18n/fr/README.md) | 🇮🇹 [Italiano](i18n/it/README.md) | 🇷🇺 [Русский](i18n/ru/README.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/README.md) | 🇩🇪 [Deutsch](i18n/de/README.md) | 🇮🇳 [हिन्दी](i18n/in/README.md) | 🇹🇭 [ไทย](i18n/th/README.md) | 🇺🇦 [Українська](i18n/uk-UA/README.md) | 🇸🇦 [العربية](i18n/ar/README.md) | 🇯🇵 [日本語](i18n/ja/README.md) | 🇻🇳 [Tiếng Việt](i18n/vi/README.md) | 🇧🇬 [Български](i18n/bg/README.md) | 🇩🇰 [Dansk](i18n/da/README.md) | 🇫🇮 [Suomi](i18n/fi/README.md) | 🇮🇱 [עברית](i18n/he/README.md) | 🇭🇺 [Magyar](i18n/hu/README.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/README.md) | 🇰🇷 [한국어](i18n/ko/README.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/README.md) | 🇳🇱 [Nederlands](i18n/nl/README.md) | 🇳🇴 [Norsk](i18n/no/README.md) | 🇵🇹 [Português (Portugal)](i18n/pt/README.md) | 🇷🇴 [Română](i18n/ro/README.md) | 🇵🇱 [Polski](i18n/pl/README.md) | 🇸🇰 [Slovenčina](i18n/sk/README.md) | 🇸🇪 [Svenska](i18n/sv/README.md) | 🇵🇭 [Filipino](i18n/phi/README.md) | 🇨🇿 [Čeština](i18n/cs/README.md) diff --git a/docs/guides/I18N.md b/docs/guides/I18N.md index 96fe1902ae..aa4af26241 100644 --- a/docs/guides/I18N.md +++ b/docs/guides/I18N.md @@ -1,3 +1,9 @@ +--- +title: "i18n — Internationalization Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # i18n — Internationalization Guide OmniRoute supports **30 languages** with full dashboard UI translation, translated documentation, and RTL support for Arabic and Hebrew. diff --git a/docs/guides/PWA_GUIDE.md b/docs/guides/PWA_GUIDE.md index a775bb2c9d..c52a35ddb3 100644 --- a/docs/guides/PWA_GUIDE.md +++ b/docs/guides/PWA_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Progressive Web App (PWA) Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Progressive Web App (PWA) Guide OmniRoute ships as a fully installable Progressive Web App. When you access the dashboard from any mobile browser — Android (Chrome) or iOS (Safari) — you can "Add to Home Screen" and get a native app-like experience with no app store required. diff --git a/docs/guides/SETUP_GUIDE.md b/docs/guides/SETUP_GUIDE.md index 2183af3570..cfa7663357 100644 --- a/docs/guides/SETUP_GUIDE.md +++ b/docs/guides/SETUP_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "📖 Setup Guide — OmniRoute" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # 📖 Setup Guide — OmniRoute > Complete setup reference for OmniRoute. For the quick version, see the [Quick Start in README](../README.md#-quick-start). diff --git a/docs/guides/TERMUX_GUIDE.md b/docs/guides/TERMUX_GUIDE.md index bdc13f15d3..6b8a8b3306 100644 --- a/docs/guides/TERMUX_GUIDE.md +++ b/docs/guides/TERMUX_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Termux Headless Setup" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Termux Headless Setup OmniRoute can run as a headless server on Android through Termux. The Electron desktop app is not supported in Termux, but the web dashboard and OpenAI-compatible API work from the local browser or from other devices on the same network. diff --git a/docs/guides/TROUBLESHOOTING.md b/docs/guides/TROUBLESHOOTING.md index 4918697c5a..162c4312cc 100644 --- a/docs/guides/TROUBLESHOOTING.md +++ b/docs/guides/TROUBLESHOOTING.md @@ -1,3 +1,9 @@ +--- +title: "Troubleshooting" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Troubleshooting 🌐 **Languages:** 🇺🇸 [English](./TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md) | 🇨🇿 [Čeština](i18n/cs/TROUBLESHOOTING.md) diff --git a/docs/guides/UNINSTALL.md b/docs/guides/UNINSTALL.md index 0d87fb711f..61ecc3f017 100644 --- a/docs/guides/UNINSTALL.md +++ b/docs/guides/UNINSTALL.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute — Uninstall Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute — Uninstall Guide 🌐 **Languages:** 🇺🇸 [English](./UNINSTALL.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/UNINSTALL.md) | 🇪🇸 [Español](i18n/es/UNINSTALL.md) | 🇫🇷 [Français](i18n/fr/UNINSTALL.md) | 🇮🇹 [Italiano](i18n/it/UNINSTALL.md) | 🇷🇺 [Русский](i18n/ru/UNINSTALL.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/UNINSTALL.md) | 🇩🇪 [Deutsch](i18n/de/UNINSTALL.md) | 🇮🇳 [हिन्दी](i18n/in/UNINSTALL.md) | 🇹🇭 [ไทย](i18n/th/UNINSTALL.md) | 🇺🇦 [Українська](i18n/uk-UA/UNINSTALL.md) | 🇸🇦 [العربية](i18n/ar/UNINSTALL.md) | 🇯🇵 [日本語](i18n/ja/UNINSTALL.md) | 🇻🇳 [Tiếng Việt](i18n/vi/UNINSTALL.md) | 🇧🇬 [Български](i18n/bg/UNINSTALL.md) | 🇩🇰 [Dansk](i18n/da/UNINSTALL.md) | 🇫🇮 [Suomi](i18n/fi/UNINSTALL.md) | 🇮🇱 [עברית](i18n/he/UNINSTALL.md) | 🇭🇺 [Magyar](i18n/hu/UNINSTALL.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/UNINSTALL.md) | 🇰🇷 [한국어](i18n/ko/UNINSTALL.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/UNINSTALL.md) | 🇳🇱 [Nederlands](i18n/nl/UNINSTALL.md) | 🇳🇴 [Norsk](i18n/no/UNINSTALL.md) | 🇵🇹 [Português (Portugal)](i18n/pt/UNINSTALL.md) | 🇷🇴 [Română](i18n/ro/UNINSTALL.md) | 🇵🇱 [Polski](i18n/pl/UNINSTALL.md) | 🇸🇰 [Slovenčina](i18n/sk/UNINSTALL.md) | 🇸🇪 [Svenska](i18n/sv/UNINSTALL.md) | 🇵🇭 [Filipino](i18n/phi/UNINSTALL.md) | 🇨🇿 [Čeština](i18n/cs/UNINSTALL.md) diff --git a/docs/guides/USER_GUIDE.md b/docs/guides/USER_GUIDE.md index d03b3cb5bb..40d684b49a 100644 --- a/docs/guides/USER_GUIDE.md +++ b/docs/guides/USER_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "User Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # User Guide 🌐 **Languages:** 🇺🇸 [English](./USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/USER_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) | 🇨🇿 [Čeština](i18n/cs/USER_GUIDE.md) diff --git a/docs/ops/COVERAGE_PLAN.md b/docs/ops/COVERAGE_PLAN.md index 9ef6e19962..32bb9dde71 100644 --- a/docs/ops/COVERAGE_PLAN.md +++ b/docs/ops/COVERAGE_PLAN.md @@ -1,3 +1,9 @@ +--- +title: "Test Coverage Plan" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Test Coverage Plan Last updated: 2026-05-13 diff --git a/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md b/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md index 9144cd8ea9..d9a40a64c8 100644 --- a/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md +++ b/docs/ops/FLY_IO_DEPLOYMENT_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute Fly.io 部署指南" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute Fly.io 部署指南 本文档记录 OmniRoute 在 Fly.io 上的实际部署方法,适用于两类场景: diff --git a/docs/ops/PROXY_GUIDE.md b/docs/ops/PROXY_GUIDE.md index 6955c168f7..4c7f7b05a4 100644 --- a/docs/ops/PROXY_GUIDE.md +++ b/docs/ops/PROXY_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "🌐 OmniRoute Proxy Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # 🌐 OmniRoute Proxy Guide > **Bypass geographic blocks, protect your identity, and route AI traffic through any proxy — with zero configuration complexity.** diff --git a/docs/ops/RELEASE_CHECKLIST.md b/docs/ops/RELEASE_CHECKLIST.md index 6c9d73edc5..ae23447060 100644 --- a/docs/ops/RELEASE_CHECKLIST.md +++ b/docs/ops/RELEASE_CHECKLIST.md @@ -1,3 +1,9 @@ +--- +title: "Release Checklist" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Release Checklist > **Last updated:** 2026-05-13 — v3.8.0 diff --git a/docs/ops/TUNNELS_GUIDE.md b/docs/ops/TUNNELS_GUIDE.md index a3d8f8284b..1861a0fa79 100644 --- a/docs/ops/TUNNELS_GUIDE.md +++ b/docs/ops/TUNNELS_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Tunnels Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Tunnels Guide > **Source of truth:** `src/lib/{cloudflaredTunnel,ngrokTunnel,tailscaleTunnel}.ts`, `src/app/api/tunnels/` diff --git a/docs/ops/VM_DEPLOYMENT_GUIDE.md b/docs/ops/VM_DEPLOYMENT_GUIDE.md index 3c334def6e..32a8ea1369 100644 --- a/docs/ops/VM_DEPLOYMENT_GUIDE.md +++ b/docs/ops/VM_DEPLOYMENT_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute — Deployment Guide on VM with Cloudflare" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute — Deployment Guide on VM with Cloudflare 🌐 **Languages:** 🇺🇸 [English](./VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](i18n/es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](i18n/fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](i18n/bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](i18n/he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](i18n/ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](i18n/cs/VM_DEPLOYMENT_GUIDE.md) diff --git a/docs/reference/API_REFERENCE.md b/docs/reference/API_REFERENCE.md index 861bd0cf07..d0b5c97c3d 100644 --- a/docs/reference/API_REFERENCE.md +++ b/docs/reference/API_REFERENCE.md @@ -1,3 +1,9 @@ +--- +title: "API Reference" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # API Reference 🌐 **Languages:** 🇺🇸 [English](./API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md) | 🇨🇿 [Čeština](i18n/cs/API_REFERENCE.md) diff --git a/docs/reference/CLI-TOOLS.md b/docs/reference/CLI-TOOLS.md index 666afbd6f2..ff7e73ae28 100644 --- a/docs/reference/CLI-TOOLS.md +++ b/docs/reference/CLI-TOOLS.md @@ -1,3 +1,9 @@ +--- +title: "CLI Tools — OmniRoute v3.8.0" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # CLI Tools — OmniRoute v3.8.0 Last updated: 2026-05-13 diff --git a/docs/reference/ENVIRONMENT.md b/docs/reference/ENVIRONMENT.md index 81af365f9e..0aff6b6c2a 100644 --- a/docs/reference/ENVIRONMENT.md +++ b/docs/reference/ENVIRONMENT.md @@ -1,3 +1,9 @@ +--- +title: "Environment Variables Reference" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Environment Variables Reference > Complete reference for every environment variable recognized by OmniRoute. diff --git a/docs/reference/FREE_TIERS.md b/docs/reference/FREE_TIERS.md index cc10dcdd39..1853cf78e6 100644 --- a/docs/reference/FREE_TIERS.md +++ b/docs/reference/FREE_TIERS.md @@ -1,3 +1,9 @@ +--- +title: "Free Tiers" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Free Tiers > **Last consolidated:** 2026-05-13 — OmniRoute v3.8.0 diff --git a/docs/reference/PROVIDER_REFERENCE.md b/docs/reference/PROVIDER_REFERENCE.md index ad0abb554d..74e6343d0e 100644 --- a/docs/reference/PROVIDER_REFERENCE.md +++ b/docs/reference/PROVIDER_REFERENCE.md @@ -1,3 +1,9 @@ +--- +title: "Provider Reference" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Provider Reference > **Auto-generated** from `src/shared/constants/providers.ts` — do not edit by hand. diff --git a/docs/routing/AUTO-COMBO.md b/docs/routing/AUTO-COMBO.md index 689dd33f3a..eb12811af1 100644 --- a/docs/routing/AUTO-COMBO.md +++ b/docs/routing/AUTO-COMBO.md @@ -1,3 +1,9 @@ +--- +title: "OmniRoute Auto-Combo Engine" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # OmniRoute Auto-Combo Engine > Self-managing model chains with adaptive scoring + zero-config auto-routing diff --git a/docs/routing/REASONING_REPLAY.md b/docs/routing/REASONING_REPLAY.md index e7a8811df7..adefd7983a 100644 --- a/docs/routing/REASONING_REPLAY.md +++ b/docs/routing/REASONING_REPLAY.md @@ -1,3 +1,9 @@ +--- +title: "Reasoning Replay Cache" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Reasoning Replay Cache > **Source of truth:** `src/lib/db/reasoningCache.ts`, `open-sse/services/reasoningCache.ts` diff --git a/docs/security/COMPLIANCE.md b/docs/security/COMPLIANCE.md index 982369313f..ce4c631f0a 100644 --- a/docs/security/COMPLIANCE.md +++ b/docs/security/COMPLIANCE.md @@ -1,3 +1,9 @@ +--- +title: "Compliance & Audit" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Compliance & Audit > **Source of truth:** `src/lib/compliance/`, `src/app/api/compliance/` diff --git a/docs/security/GUARDRAILS.md b/docs/security/GUARDRAILS.md index 6185dd08f2..29d6d5a519 100644 --- a/docs/security/GUARDRAILS.md +++ b/docs/security/GUARDRAILS.md @@ -1,3 +1,9 @@ +--- +title: "Guardrails" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Guardrails > **Source of truth:** `src/lib/guardrails/` diff --git a/docs/security/STEALTH_GUIDE.md b/docs/security/STEALTH_GUIDE.md index 308d663e6c..f814c61b41 100644 --- a/docs/security/STEALTH_GUIDE.md +++ b/docs/security/STEALTH_GUIDE.md @@ -1,3 +1,9 @@ +--- +title: "Stealth Guide" +version: 3.8.0 +lastUpdated: 2026-05-13 +--- + # Stealth Guide > **Source of truth:** `open-sse/utils/tlsClient.ts`, `open-sse/services/{chatgptTlsClient,claudeCodeCCH,claudeCodeFingerprint,claudeCodeObfuscation,claudeCodeCompatible,antigravityObfuscation}.ts`, `open-sse/config/cliFingerprints.ts`, `src/mitm/` diff --git a/scripts/docs/add-frontmatter.mjs b/scripts/docs/add-frontmatter.mjs new file mode 100644 index 0000000000..d65e4211dd --- /dev/null +++ b/scripts/docs/add-frontmatter.mjs @@ -0,0 +1,148 @@ +#!/usr/bin/env node +/** + * add-frontmatter.mjs — one-shot helper that ensures every documentation + * file under docs//*.md and docs/README.md has a YAML frontmatter + * header with `title`, `version`, and `lastUpdated`. + * + * Idempotent: docs that already have a `---` block at the top are skipped + * (the existing frontmatter is preserved as-is). Files without a leading + * `# Title` heading fall back to the basename humanized as a title. + * + * Excludes: docs/i18n/, docs/screenshots/, docs/superpowers/, + * docs/diagrams/exported/. Subfolder READMEs are included. + * + * Usage: node scripts/docs/add-frontmatter.mjs [--version X.Y.Z] [--date YYYY-MM-DD] + */ + +import { promises as fs } from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const ROOT = path.resolve(__dirname, "..", ".."); +const DOCS_DIR = path.join(ROOT, "docs"); + +const EXCLUDE_PREFIXES = [ + "docs/i18n/", + "docs/screenshots/", + "docs/superpowers/", + "docs/diagrams/exported/", +]; + +const args = process.argv.slice(2); +let version = "3.8.0"; +let lastUpdated = "2026-05-13"; +for (let i = 0; i < args.length; i += 1) { + if (args[i] === "--version" && args[i + 1]) { + version = args[i + 1]; + i += 1; + } else if (args[i] === "--date" && args[i + 1]) { + lastUpdated = args[i + 1]; + i += 1; + } +} + +async function walk(dir, files = []) { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const entry of entries) { + const full = path.join(dir, entry.name); + if (entry.isDirectory()) { + await walk(full, files); + } else if (entry.isFile() && entry.name.endsWith(".md")) { + files.push(full); + } + } + return files; +} + +function isExcluded(rel) { + return EXCLUDE_PREFIXES.some((p) => rel === p || rel.startsWith(p)); +} + +function hasFrontmatter(content) { + return /^---\r?\n/.test(content); +} + +function extractTopHeading(content) { + const lines = content.replace(/^/, "").split(/\r?\n/); + for (const line of lines) { + const m = line.match(/^#\s+(.+?)\s*$/); + if (m) return m[1].trim(); + // Allow blank/HTML-comment lines before the first heading + if (line.trim() === "" || /^