From 9d84dabbe420f77ea61e125544556c7769bfb20b Mon Sep 17 00:00:00 2001 From: Yuriy Andamasov Date: Thu, 7 May 2026 14:46:50 +0300 Subject: general: T8595: switch CLAUDE.md to AGENTS.md (+ Copilot symlink) --- .github/copilot-instructions.md | 81 +------------- AGENTS.md | 242 ++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 242 ---------------------------------------- 3 files changed, 243 insertions(+), 322 deletions(-) mode change 100644 => 120000 .github/copilot-instructions.md create mode 100644 AGENTS.md delete mode 100644 CLAUDE.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md deleted file mode 100644 index 30fa5800..00000000 --- a/.github/copilot-instructions.md +++ /dev/null @@ -1,80 +0,0 @@ -## VyOS Documentation Project - -This is VyOS user documentation written in reStructuredText (RST) and built with Sphinx. - -### Review Scope - -When reviewing pull requests, only flag issues **introduced by the PR's changes**. Do not flag pre-existing issues in unchanged lines. Compare against the base branch to determine what was actually changed. - -### RST Heading Hierarchy - -All files must use this heading order: - -``` -##### (Title — one per file, with overline) -***** (Chapters) -===== (Sections) ------ (Subsections) -^^^^^ (Subsubsections) -""""" (Paragraphs) -``` - -### Line Length - -Maximum 80 characters per line. Exception: content inside `.. code-block::` directives is **exempt** — they render with `
` tags and preserve source formatting. Do not flag long lines inside code blocks.
-
-### Linter Suppression Markers
-
-`.. stop_vyoslinter` and `.. start_vyoslinter` are RST comments used to suppress CI linter checks. Key conventions:
-
-- When used **inside an indented directive** (`.. cfgcmd::`, `.. opcmd::`, list items), markers should match the surrounding indentation to stay within the block.
-- When used **at top level** (outside any directive), markers are placed at column 0.
-- Both patterns exist in this repo. Do not flag either placement as incorrect.
-- They must always appear in pairs (stop then start). A missing `start_vyoslinter` is a real issue.
-- A `stop_vyoslinter` that covers a large section is acceptable when the content requires it (e.g., files full of real debug output with production IPs).
-
-### IP Address Rules
-
-The CI linter checks IP addresses. These are **allowed without suppression** — do not flag them:
-
-- RFC 5737 documentation addresses: `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`
-- RFC 3849 documentation IPv6: `2001:db8::/32`
-- RFC 1918 private ranges: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`
-- Loopback (`127.0.0.0/8`), link-local (`169.254.0.0/16`), `0.0.0.0/0`
-
-Real public IPs (e.g., `8.8.8.8`) require `stop/start_vyoslinter` suppression. Do not suggest replacing them with documentation addresses if the example intentionally uses real IPs.
-
-### TODO Markers
-
-`.. TODO::` directives serve two purposes in this repo:
-
-1. **Tracking markers** on pages that need `cfgcmd`/`opcmd` conversion (these are intentionally added).
-2. **Stale markers** on pages that already have full content (these should be removed).
-
-A PR that removes some TODOs and adds others is not contradictory — the intent matters.
-
-### VyOS Directives
-
-- `.. cfgcmd::` for configuration mode commands
-- `.. opcmd::` for operational mode commands
-- Do not convert these to plain `.. code-block::` — they are tracked for command coverage.
-
-### YAML in Code Blocks
-
-Ansible playbook examples in `.. code-block::` use RST indentation (typically 4 spaces from the directive). The YAML indentation within the block may differ from standalone YAML files. Verify carefully before flagging YAML as invalid — count spaces from the code-block's own indentation base, not from column 0.
-
-### Page Structure
-
-Configuration pages follow this order: Theory, Configuration (cfgcmd), Examples, Known Issues, Debugging.
-
-### Known False Positives
-
-Do **not** flag the following — they have been verified as correct or intentional:
-
-- **Markdown tables rendering with `||`**: Diff views may show table pipes as double-pipes. Check the raw source file before flagging.
-- **`stop/start_vyoslinter` at column 0 inside directives**: This is one of two accepted patterns. The other is indented markers matching the directive. Both are valid.
-- **RFC 1918 addresses without linter suppression**: Private IPs (`10.x`, `172.16.x`, `192.168.x`) are allowed. Do not suggest adding `stop/start_vyoslinter` around them.
-- **Long lines inside `.. code-block::`**: Code blocks are exempt from the 80-character line limit.
-- **Pre-existing typos or grammar issues in unchanged lines**: Only flag issues introduced by the current PR's diff. If a typo exists on an unchanged line, it is out of scope.
-- **Ansible YAML indentation in RST code blocks**: YAML inside `.. code-block::` is indented relative to the directive, not column 0. Verify from the code-block's indentation base before flagging as invalid.
-- **Adding `.. TODO::` while removing others**: Tracking TODOs on pages needing `cfgcmd` conversion is intentional. Removing stale TODOs on completed pages is also intentional. Both can happen in the same PR.
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
new file mode 120000
index 00000000..be77ac83
--- /dev/null
+++ b/.github/copilot-instructions.md
@@ -0,0 +1 @@
+../AGENTS.md
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 00000000..9b4cf05e
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,242 @@
+# AGENTS.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
+
+## Project
+
+VyOS user documentation, built with Sphinx and hosted on Read the Docs at https://docs.vyos.io. Sources are MyST Markdown (`.md`) for migrated pages and RST (`.rst`) for the rest. Both formats are first-class to Sphinx; MD is the canonical source for any page that has been migrated, and RST is the canonical source for pages that haven't.
+
+A small swap mechanism exists for the rare case where a maintainer needs to render the legacy RST version of a page that already has an MD primary — see `RST override mechanism` below. The override list is empty by default.
+
+## Build
+
+```bash
+# Docker (recommended — bundles Sphinx and the MyST/RTD plugin set)
+docker build -t vyos/vyos-documentation docker
+docker run --rm -it -v "$(pwd)":/vyos -w /vyos/docs \
+  -e GOSU_UID=$(id -u) -e GOSU_GID=$(id -g) \
+  vyos/vyos-documentation make html
+
+# Live-reload server on port 8000
+docker run --rm -it -p 8000:8000 -v "$(pwd)":/vyos -w /vyos/docs \
+  -e GOSU_UID=$(id -u) -e GOSU_GID=$(id -g) \
+  vyos/vyos-documentation make livehtml
+
+# Local (Python 3, see requirements.txt for pinned versions)
+pip install -r requirements.txt
+cd docs && make html
+```
+
+Output: `docs/_build/html/`.
+
+## Tests
+
+`tests/test_swap_sources.py` imports `swap_sources` from `scripts/`, which is
+not on `PYTHONPATH` by default. Run from the `tests/` directory:
+
+```bash
+cd tests
+PYTHONPATH=../scripts python -m pytest                    # all tests
+PYTHONPATH=../scripts python -m pytest test_swap_sources.py  # single file
+```
+
+## Lint
+
+The repo doesn't ship a local lint config or pin a linter binary. CI runs
+`vyoslinter` (`doc-linter.py` from the `vyos/.github` repo, via the
+`lint-doc.yml` workflow) on changed files only — see the CI section
+below. For local checks, manually grep for the rules in
+[Source conventions](#source-conventions) (line length, address space,
+suppression markers).
+
+## Branches and versions
+
+One long-lived branch per VyOS release line. Branch names are constellations sorted by area:
+
+| Branch | VyOS version |
+|--------|--------------|
+| `current` | rolling / 1.5+ (default branch — all new docs target this) |
+| `circinus` | 1.5.x |
+| `sagitta` | 1.4.x |
+| `equuleus` | 1.3.x (legacy) |
+| `crux` | 1.2.x (legacy) |
+
+PRs target `current`. After merge, request backports via Mergify comments on the PR:
+
+```
+@Mergifyio backport circinus
+@Mergifyio backport sagitta
+```
+
+Mergify is configured at the org level (no `.mergify.yml` in the repo). The PR template has a `## Backport` section to declare intent.
+
+## Architecture
+
+### Sphinx config (`docs/conf.py`)
+
+- `source_suffix = ['.rst', '.md']` — both formats build into the same site.
+- MyST extensions: `colon_fence`, `deflist`, `fieldlist`, `substitution`.
+- `myst_fence_as_directive = ["cfgcmd", "opcmd", "cmdincludemd"]` — MyST fences with these names get parsed as if they were RST directives. This is how command pages stay format-portable.
+- Custom modules live in `docs/_ext/` (only files listed in `extensions = [...]` in `conf.py` are actual Sphinx extensions; the others are support scripts loaded ad hoc):
+  - `vyos.py` (Sphinx extension, registered as `vyos`) — defines the `cfgcmd`, `opcmd`, `cmdinclude`, `cmdincludemd`, `cfgcmdlist`, `opcmdlist` directives and `cfgcmd`/`opcmd` roles that drive command coverage tracking.
+  - `autosectionlabel.py` (Sphinx extension, registered as `autosectionlabel`) — connects to `doctree-read` to register sections as labels.
+  - `testcoverage.py` — standalone helper that reads VyOS XML command definitions and exposes coverage stats; not a Sphinx extension.
+  - `releasenotes.py` — standalone release-notes/changelog generator script; not a Sphinx extension.
+
+### RST override mechanism
+
+For pages that have been migrated from RST to MyST:
+
+- `docs//.md` — canonical MD source (primary).
+- `docs//rst-.rst` — preserved RST sibling kept around as an override
+  option. The `rst-` prefix applies only to the **filename**, not the directory, so
+  `configuration/firewall/zone` maps to `docs/configuration/firewall/rst-zone.rst`
+  (not `docs/rst-configuration/firewall/zone.rst`). Excluded from the build by
+  `exclude_patterns` in `conf.py`.
+- `docs/_rst_overrides.txt` — one stem per line, relative to `docs/` (e.g.
+  `configuration/firewall/zone`). Pages listed here render from
+  `rst-.rst` instead of `.md`. Empty by default.
+- `scripts/swap_sources.py` — CLI for `--swap` (apply overrides), `--restore`,
+  `--dry-run`, `--status`. Build-time state lands in
+  `docs/_build/_rst_override_state.json` and `docs/_build/_md_exclude.txt`
+  (gitignored).
+
+For pages that have NOT been migrated:
+
+- `docs/.rst` — original RST, no `rst-` prefix, no MD sibling.
+
+**Editing rules:**
+- Migrated page (has `.md`): edit the `.md`. Don't touch the `rst-`-prefixed sibling unless you're maintaining a parallel RST version that someone has flagged in `_rst_overrides.txt`.
+- Non-migrated page (RST-only): edit the `.rst`.
+- New page: write it as `.md` from the start. The `md-` prefix that earlier MyST migration commits used is gone — never add it.
+
+Running `make html` runs the swap automatically (it's a no-op when the override list is empty, which is the default state).
+
+### Command directives
+
+`.. cfgcmd::`, `.. opcmd::`, and `.. cmdinclude::` are the VyOS-specific Sphinx directives in RST. They are tracked for command coverage — do **not** convert them to plain `.. code-block::`. In MyST the same directives are written as fenced blocks: ```` ```{cfgcmd} set system ... ```` (enabled by `myst_fence_as_directive`). The MyST include directive is named `cmdincludemd` (not `cmdinclude`) so that template parsing follows MyST rules in MD pages and RST rules in RST pages — pick `cmdinclude` in `.rst`, `cmdincludemd` in `.md`.
+
+## Source conventions
+
+### RST heading hierarchy
+
+```
+##### Title (overline+underline, one per file)
+***** Chapters
+===== Sections
+----- Subsections
+^^^^^ Subsubsections
+""""" Paragraphs
+```
+
+The first heading in every RST file uses `#` overline+underline. Field lists (e.g., `:lastproofread:`) or labels may precede it.
+
+### Formatting
+
+- 80-character line limit (exception: inside `.. code-block::` / fenced code blocks — `
` preserves source verbatim).
+- American English.
+- Indent with 2 spaces.
+- Blank lines around headings.
+- Inline code: use double backticks per RST convention (the [Inline markup](https://docutils.sourceforge.io/docs/user/rst/quickref.html#inline-markup) section of the docutils quick reference).
+
+### IP addresses (linter-enforced)
+
+Allowed without suppression:
+- RFC 5737 IPv4 docs: `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`
+- RFC 3849 IPv6 docs: `2001:db8::/32`
+- RFC 1918 private ranges: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`
+- Loopback (`127.0.0.0/8`), link-local (`169.254.0.0/16`), `0.0.0.0/0`
+
+Allowed ASN: `64496-64511` (16-bit), `65536-65551` (32-bit).
+Allowed MAC ranges: `00-53-00`–`00-53-FF` (unicast), `90-10-00`–`90-10-FF` (multicast).
+
+**Requires `stop/start_vyoslinter` suppression:**
+- Real public IPs (e.g., `8.8.8.8` for DNS examples).
+- NAT64 well-known prefix `64:ff9b::/96`.
+- Lines over 80 chars (URLs, certificate fingerprints).
+
+### Linter suppression markers
+
+```rst
+.. stop_vyoslinter
+
+.. code-block:: none
+
+   content with real IPs or long lines here
+
+.. start_vyoslinter
+```
+
+In MyST `.md` files use the comment form `% stop_vyoslinter` / `% start_vyoslinter` for top-level Markdown content. Inside `{eval-rst}` blocks (where the embedded content is parsed as RST) keep the RST form `.. stop_vyoslinter` / `.. start_vyoslinter` — the linter scans the source line literally and only the form that matches the surrounding parser is recognized. Likewise, `.txt` template files (included via `{include}` or `cmdincludemd`) keep the RST form.
+
+Markers must always come in pairs. Indentation may match the surrounding directive (indented inside a block) or sit at column 0 (top-level) — both are valid.
+
+### Configuration page structure
+
+1. **Theory** — what it is, when to use it, relevant RFCs.
+2. **Configuration** — all CLI options as `.. cfgcmd::` (RST) or ```` ```{cfgcmd} ```` (MD).
+3. **Examples** — practical configurations with topology diagrams.
+4. **Known issues** — problems and workarounds.
+5. **Debugging** — log collection, `show` commands, state indicators.
+
+### `.. TODO::` markers
+
+Two valid uses:
+1. **Tracking** marker on pages that still need `cfgcmd`/`opcmd` conversion — intentional.
+2. **Stale** marker on pages that already have full content — should be removed.
+
+A PR that both adds and removes TODOs is not contradictory; intent matters.
+
+## LLM-Facing Files (`llms.txt`, `llms-full.txt`)
+
+Both files are regenerated on every `html` and `readthedocs` builder run.
+The `dirhtml` builder is intentionally skipped — production publishes
+only via `html`/`readthedocs`, and we don't render `llms.txt` for builds
+we don't ship. Local `make dirhtml` is a developer convenience and
+won't emit `llms.txt`.
+
+Files are shipped at the docs root for each version
+(`https://docs.vyos.io/en//llms.txt`, `.../llms-full.txt`).
+
+- **`llms-full.txt`** — auto-generated by the `sphinx_llms_txt` extension from
+  the full corpus. No curation; configured by `llms_txt_file = False` (which
+  disables the extension's *index* output, not the full output).
+- **`llms.txt`** — curated overview rendered at build time from
+  `docs/_templates/llms.txt.j2`. URLs and the version line are interpolated
+  from `html_baseurl` and `release` so the file always matches the branch.
+  The render lives in `_write_llms_txt(app, exception)` in `docs/conf.py`,
+  wired via `app.connect('build-finished', ...)`.
+
+When adding new top-level sections to the docs, add a corresponding bullet in
+`docs/_templates/llms.txt.j2`. Branch-specific differences (e.g. sagitta has
+no `vpp/index.md` or `contributing/index.md`) live in that branch's copy of the template.
+
+## Read the Docs Layout
+
+RTD slugs as of 2026-05-04 (verified via API). Re-verify via the RTD
+Versions API (project `vyos`) and update the date stamp before editing this
+table.
+
+| Slug | Verbose | Branch | Role |
+|---|---|---|---|
+| `rolling` | current | `current` | canonical for rolling/next major |
+| `1.5` | circinus | `circinus` | canonical for current LTS |
+| `1.4` | sagitta | `sagitta` | canonical for previous LTS |
+| `1.3`, `1.2` | equuleus, crux | older | canonical for older releases |
+
+URL-level redirect aliases (resolve to the canonicals above):
+`/en/latest/* → /en/rolling/`, `/en/lts/* → /en/1.5/`,
+`/en/stable/* → /en/lts/`, `/en/circinus/* → /en/1.5/`,
+`/en/sagitta/* → /en/1.4/`, `/en/equuleus/* → /en/1.3/`,
+`/en/crux/* → /en/1.2/`.
+
+`html_baseurl` per branch must point at the canonical (numeric or `rolling`),
+not the alias, so `` and the sitemap match what RTD
+serves and crawlers skip the redirect hop.
+
+## CI
+
+- **vyoslinter** (`doc-linter.py` from the `vyos/.github` repo, run via `lint-doc.yml`) — line length and IP rules, on changed files only.
+- **Sphinx build** — runs on Read the Docs for every PR; preview URL appears as a check.
+- **CLA check** — contributors must sign the VyOS CLA before merge.
+- **Conflict check** — fails the PR if it doesn't merge cleanly into base.
diff --git a/CLAUDE.md b/CLAUDE.md
deleted file mode 100644
index f4759273..00000000
--- a/CLAUDE.md
+++ /dev/null
@@ -1,242 +0,0 @@
-# CLAUDE.md
-
-This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
-
-## Project
-
-VyOS user documentation, built with Sphinx and hosted on Read the Docs at https://docs.vyos.io. Sources are MyST Markdown (`.md`) for migrated pages and RST (`.rst`) for the rest. Both formats are first-class to Sphinx; MD is the canonical source for any page that has been migrated, and RST is the canonical source for pages that haven't.
-
-A small swap mechanism exists for the rare case where a maintainer needs to render the legacy RST version of a page that already has an MD primary — see `RST override mechanism` below. The override list is empty by default.
-
-## Build
-
-```bash
-# Docker (recommended — bundles Sphinx and the MyST/RTD plugin set)
-docker build -t vyos/vyos-documentation docker
-docker run --rm -it -v "$(pwd)":/vyos -w /vyos/docs \
-  -e GOSU_UID=$(id -u) -e GOSU_GID=$(id -g) \
-  vyos/vyos-documentation make html
-
-# Live-reload server on port 8000
-docker run --rm -it -p 8000:8000 -v "$(pwd)":/vyos -w /vyos/docs \
-  -e GOSU_UID=$(id -u) -e GOSU_GID=$(id -g) \
-  vyos/vyos-documentation make livehtml
-
-# Local (Python 3, see requirements.txt for pinned versions)
-pip install -r requirements.txt
-cd docs && make html
-```
-
-Output: `docs/_build/html/`.
-
-## Tests
-
-`tests/test_swap_sources.py` imports `swap_sources` from `scripts/`, which is
-not on `PYTHONPATH` by default. Run from the `tests/` directory:
-
-```bash
-cd tests
-PYTHONPATH=../scripts python -m pytest                    # all tests
-PYTHONPATH=../scripts python -m pytest test_swap_sources.py  # single file
-```
-
-## Lint
-
-The repo doesn't ship a local lint config or pin a linter binary. CI runs
-`vyoslinter` (`doc-linter.py` from the `vyos/.github` repo, via the
-`lint-doc.yml` workflow) on changed files only — see the CI section
-below. For local checks, manually grep for the rules in
-[Source conventions](#source-conventions) (line length, address space,
-suppression markers).
-
-## Branches and versions
-
-One long-lived branch per VyOS release line. Branch names are constellations sorted by area:
-
-| Branch | VyOS version |
-|--------|--------------|
-| `current` | rolling / 1.5+ (default branch — all new docs target this) |
-| `circinus` | 1.5.x |
-| `sagitta` | 1.4.x |
-| `equuleus` | 1.3.x (legacy) |
-| `crux` | 1.2.x (legacy) |
-
-PRs target `current`. After merge, request backports via Mergify comments on the PR:
-
-```
-@Mergifyio backport circinus
-@Mergifyio backport sagitta
-```
-
-Mergify is configured at the org level (no `.mergify.yml` in the repo). The PR template has a `## Backport` section to declare intent.
-
-## Architecture
-
-### Sphinx config (`docs/conf.py`)
-
-- `source_suffix = ['.rst', '.md']` — both formats build into the same site.
-- MyST extensions: `colon_fence`, `deflist`, `fieldlist`, `substitution`.
-- `myst_fence_as_directive = ["cfgcmd", "opcmd", "cmdincludemd"]` — MyST fences with these names get parsed as if they were RST directives. This is how command pages stay format-portable.
-- Custom modules live in `docs/_ext/` (only files listed in `extensions = [...]` in `conf.py` are actual Sphinx extensions; the others are support scripts loaded ad hoc):
-  - `vyos.py` (Sphinx extension, registered as `vyos`) — defines the `cfgcmd`, `opcmd`, `cmdinclude`, `cmdincludemd`, `cfgcmdlist`, `opcmdlist` directives and `cfgcmd`/`opcmd` roles that drive command coverage tracking.
-  - `autosectionlabel.py` (Sphinx extension, registered as `autosectionlabel`) — connects to `doctree-read` to register sections as labels.
-  - `testcoverage.py` — standalone helper that reads VyOS XML command definitions and exposes coverage stats; not a Sphinx extension.
-  - `releasenotes.py` — standalone release-notes/changelog generator script; not a Sphinx extension.
-
-### RST override mechanism
-
-For pages that have been migrated from RST to MyST:
-
-- `docs//.md` — canonical MD source (primary).
-- `docs//rst-.rst` — preserved RST sibling kept around as an override
-  option. The `rst-` prefix applies only to the **filename**, not the directory, so
-  `configuration/firewall/zone` maps to `docs/configuration/firewall/rst-zone.rst`
-  (not `docs/rst-configuration/firewall/zone.rst`). Excluded from the build by
-  `exclude_patterns` in `conf.py`.
-- `docs/_rst_overrides.txt` — one stem per line, relative to `docs/` (e.g.
-  `configuration/firewall/zone`). Pages listed here render from
-  `rst-.rst` instead of `.md`. Empty by default.
-- `scripts/swap_sources.py` — CLI for `--swap` (apply overrides), `--restore`,
-  `--dry-run`, `--status`. Build-time state lands in
-  `docs/_build/_rst_override_state.json` and `docs/_build/_md_exclude.txt`
-  (gitignored).
-
-For pages that have NOT been migrated:
-
-- `docs/.rst` — original RST, no `rst-` prefix, no MD sibling.
-
-**Editing rules:**
-- Migrated page (has `.md`): edit the `.md`. Don't touch the `rst-`-prefixed sibling unless you're maintaining a parallel RST version that someone has flagged in `_rst_overrides.txt`.
-- Non-migrated page (RST-only): edit the `.rst`.
-- New page: write it as `.md` from the start. The `md-` prefix that earlier MyST migration commits used is gone — never add it.
-
-Running `make html` runs the swap automatically (it's a no-op when the override list is empty, which is the default state).
-
-### Command directives
-
-`.. cfgcmd::`, `.. opcmd::`, and `.. cmdinclude::` are the VyOS-specific Sphinx directives in RST. They are tracked for command coverage — do **not** convert them to plain `.. code-block::`. In MyST the same directives are written as fenced blocks: ```` ```{cfgcmd} set system ... ```` (enabled by `myst_fence_as_directive`). The MyST include directive is named `cmdincludemd` (not `cmdinclude`) so that template parsing follows MyST rules in MD pages and RST rules in RST pages — pick `cmdinclude` in `.rst`, `cmdincludemd` in `.md`.
-
-## Source conventions
-
-### RST heading hierarchy
-
-```
-##### Title (overline+underline, one per file)
-***** Chapters
-===== Sections
------ Subsections
-^^^^^ Subsubsections
-""""" Paragraphs
-```
-
-The first heading in every RST file uses `#` overline+underline. Field lists (e.g., `:lastproofread:`) or labels may precede it.
-
-### Formatting
-
-- 80-character line limit (exception: inside `.. code-block::` / fenced code blocks — `
` preserves source verbatim).
-- American English.
-- Indent with 2 spaces.
-- Blank lines around headings.
-- Inline code: use double backticks per RST convention (the [Inline markup](https://docutils.sourceforge.io/docs/user/rst/quickref.html#inline-markup) section of the docutils quick reference).
-
-### IP addresses (linter-enforced)
-
-Allowed without suppression:
-- RFC 5737 IPv4 docs: `192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`
-- RFC 3849 IPv6 docs: `2001:db8::/32`
-- RFC 1918 private ranges: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`
-- Loopback (`127.0.0.0/8`), link-local (`169.254.0.0/16`), `0.0.0.0/0`
-
-Allowed ASN: `64496-64511` (16-bit), `65536-65551` (32-bit).
-Allowed MAC ranges: `00-53-00`–`00-53-FF` (unicast), `90-10-00`–`90-10-FF` (multicast).
-
-**Requires `stop/start_vyoslinter` suppression:**
-- Real public IPs (e.g., `8.8.8.8` for DNS examples).
-- NAT64 well-known prefix `64:ff9b::/96`.
-- Lines over 80 chars (URLs, certificate fingerprints).
-
-### Linter suppression markers
-
-```rst
-.. stop_vyoslinter
-
-.. code-block:: none
-
-   content with real IPs or long lines here
-
-.. start_vyoslinter
-```
-
-In MyST `.md` files use the comment form `% stop_vyoslinter` / `% start_vyoslinter` for top-level Markdown content. Inside `{eval-rst}` blocks (where the embedded content is parsed as RST) keep the RST form `.. stop_vyoslinter` / `.. start_vyoslinter` — the linter scans the source line literally and only the form that matches the surrounding parser is recognized. Likewise, `.txt` template files (included via `{include}` or `cmdincludemd`) keep the RST form.
-
-Markers must always come in pairs. Indentation may match the surrounding directive (indented inside a block) or sit at column 0 (top-level) — both are valid.
-
-### Configuration page structure
-
-1. **Theory** — what it is, when to use it, relevant RFCs.
-2. **Configuration** — all CLI options as `.. cfgcmd::` (RST) or ```` ```{cfgcmd} ```` (MD).
-3. **Examples** — practical configurations with topology diagrams.
-4. **Known issues** — problems and workarounds.
-5. **Debugging** — log collection, `show` commands, state indicators.
-
-### `.. TODO::` markers
-
-Two valid uses:
-1. **Tracking** marker on pages that still need `cfgcmd`/`opcmd` conversion — intentional.
-2. **Stale** marker on pages that already have full content — should be removed.
-
-A PR that both adds and removes TODOs is not contradictory; intent matters.
-
-## LLM-Facing Files (`llms.txt`, `llms-full.txt`)
-
-Both files are regenerated on every `html` and `readthedocs` builder run.
-The `dirhtml` builder is intentionally skipped — production publishes
-only via `html`/`readthedocs`, and we don't render `llms.txt` for builds
-we don't ship. Local `make dirhtml` is a developer convenience and
-won't emit `llms.txt`.
-
-Files are shipped at the docs root for each version
-(`https://docs.vyos.io/en//llms.txt`, `.../llms-full.txt`).
-
-- **`llms-full.txt`** — auto-generated by the `sphinx_llms_txt` extension from
-  the full corpus. No curation; configured by `llms_txt_file = False` (which
-  disables the extension's *index* output, not the full output).
-- **`llms.txt`** — curated overview rendered at build time from
-  `docs/_templates/llms.txt.j2`. URLs and the version line are interpolated
-  from `html_baseurl` and `release` so the file always matches the branch.
-  The render lives in `_write_llms_txt(app, exception)` in `docs/conf.py`,
-  wired via `app.connect('build-finished', ...)`.
-
-When adding new top-level sections to the docs, add a corresponding bullet in
-`docs/_templates/llms.txt.j2`. Branch-specific differences (e.g. sagitta has
-no `vpp/index.md` or `contributing/index.md`) live in that branch's copy of the template.
-
-## Read the Docs Layout
-
-RTD slugs as of 2026-05-04 (verified via API). Re-verify via the RTD
-Versions API (project `vyos`) and update the date stamp before editing this
-table.
-
-| Slug | Verbose | Branch | Role |
-|---|---|---|---|
-| `rolling` | current | `current` | canonical for rolling/next major |
-| `1.5` | circinus | `circinus` | canonical for current LTS |
-| `1.4` | sagitta | `sagitta` | canonical for previous LTS |
-| `1.3`, `1.2` | equuleus, crux | older | canonical for older releases |
-
-URL-level redirect aliases (resolve to the canonicals above):
-`/en/latest/* → /en/rolling/`, `/en/lts/* → /en/1.5/`,
-`/en/stable/* → /en/lts/`, `/en/circinus/* → /en/1.5/`,
-`/en/sagitta/* → /en/1.4/`, `/en/equuleus/* → /en/1.3/`,
-`/en/crux/* → /en/1.2/`.
-
-`html_baseurl` per branch must point at the canonical (numeric or `rolling`),
-not the alias, so `` and the sitemap match what RTD
-serves and crawlers skip the redirect hop.
-
-## CI
-
-- **vyoslinter** (`doc-linter.py` from the `vyos/.github` repo, run via `lint-doc.yml`) — line length and IP rules, on changed files only.
-- **Sphinx build** — runs on Read the Docs for every PR; preview URL appears as a check.
-- **CLA check** — contributors must sign the VyOS CLA before merge.
-- **Conflict check** — fails the PR if it doesn't merge cleanly into base.
-- 
cgit v1.2.3