MkDocs Structure Apply
Operationalises spec/project/mkdocs-structure/<canonical_language>.md inside the current repository. The skill audits the current MkDocs wiring against the baseline plus every active project-type-specific extension spec, proposes the concrete file-level changes the spec requires, and—with explicit per-item user consent—applies them.
When the spec isn't present in the target repository, fall back to the copy shipped by the nolte-shared plugin (read it at runtime from ${CLAUDE_PLUGIN_ROOT}/spec/project/mkdocs-structure/<canonical_language>.md). Never invent requirements that don't appear in the spec.
Why this is a skill, not an agent
Per spec/claude/skill-vs-agent/ §Decision dimensions, this capability is a skill because:
- Mid-flow user approval is the contract. Every scaffold or patch decision (mkdocs.yml plugin additions, docs// section folders, dep-manifest pins, Taskfile wiring) is written only with explicit per-change confirmation; the audit is read-only and the apply step is a sequence of approvals an agent's fire-and-forget shape can't carry.
- Persistent on-disk output that flows back into the main conversation. The audit table, the per-item proposals, and the build-verification output all surface in the conversation so the user can decide; isolating them in a structured-report boundary would obscure the per-file approval surface.
- Orchestrator pattern. The skill can dispatch the
audience-doc-author agent for page-content authoring or the docs-dry-refactor skill for DRY refactoring; per spec/claude/skill-vs-agent/ §Hybrid pattern, the orchestrator is always a skill.
- Precedent. Follows the same audit + scaffold + patch shape as
project-structure-apply and skill-agent-catalog-apply; portfolio-wide consistency (spec/claude/skill-vs-agent/ §Portfolio-wide consistency) favours the same artifact type.
- Counter-dimension considered. A narrower agent could specialise on mkdocs.yml-patch generation and gain on context-window protection, but the high-impact part is the per-item approval dialogue and the build-verification loop, not the boilerplate generation; skill wins.
User-language policy
Detect the user's language from their message and respond in it. Generated file contents (mkdocs.yml, docs/<lang>/index.md, section index stubs, dep-manifest patches, Taskfile.yml targets) are always written in English so portfolio-wide automation stays predictable. Comments inside generated files are English as well.
Tools used
Tools this skill uses: Read, Write, Edit, Glob, Grep, Bash.
Read / Glob / Grep for repository inspection (mkdocs.yml, docs// trees, dep manifests, page frontmatter, active extension-spec markers).
Write / Edit for scaffold and patch operations on mkdocs.yml, docs trees, and dep manifests; never overwriting existing config wholesale.
Bash is necessary for mkdocs build --strict verification, task docs local invocation, and detecting the project's package manager (pyproject.toml shape, uv.lock / poetry.lock / requirements*.txt presence). The skill never runs destructive bash (git push, gh pr create, pip install, rm -rf).
- No
WebFetch / WebSearch: the spec is the only source of truth; baseline plugin pins are read from the project's existing dep manifest, never from the network.
Preconditions
Before doing anything:
- Confirm the working directory is a git repository (
git rev-parse --is-inside-work-tree).
- Locate
spec/project/mkdocs-structure/<canonical_language>.md—either in the target repo or via the nolte-shared plugin. If neither is reachable, stop and ask the user which spec source to use (matches the spec's §Extension hooks §"Project-type discovery" fallback pattern).
- Determine the operation:
- If
mkdocs.yml is absent → scaffold (default).
- If
mkdocs.yml is present → patch (or audit when the user explicitly asks for a read-only conformance check).
- Detect active extension specs by scanning marker files at the repo root:
.claude-plugin/plugin.json activates spec/claude/skill-agent-catalog/; cookiecutter.json plus {{cookiecutter.project_slug}}/ activates a future cookiecutter-template-docs spec; and so on. Read every active extension spec at runtime; compose its MUSTs additively with the baseline (per the spec's §Extension hooks rule "every active extension's MUSTs are additive to the baseline MUSTs").
- Resolve the language list from
spec/.spec-config.yml languages. If that file is absent, ask the user which languages the docs should ship in; default to a single en only after explicit confirmation.
- Check for uncommitted changes in
mkdocs.yml, docs/, the dep manifest, and Taskfile.yml. If the tree is dirty there, report and ask whether to stash, commit, or abort—never overwrite uncommitted work.
Operations
Read references/operations.md when executing any of the operations below in detail.
1. audit (read-only)
Walk the spec's Acceptance Criteria and every active extension spec's MUSTs; classify each finding as pass, missing, or drift grouped by spec area (Site layout, Top-level navigation, Plugin baseline, Per-page structure, Content modes, Snippet inclusion, Site identity (site_url), i18n parity, Build verification, Extension conformance, Cap check). The Site-identity check reports a missing finding when site_url is absent and a drift finding when it doesn't match the repository's published base URL; when mkdocs-static-i18n declares more than one language, treat a missing site_url as critical. Audit is read-only—never autofix.
2. scaffold (greenfield: mkdocs.yml absent)
Create mkdocs.yml with Material theme, baseline plugins (search, i18n, include-markdown), site_url derived from the repository's coordinates (see Gotchas for the derivation rule), seven standard nav sections, and nav_translations skeleton; scaffold docs/<lang>/ trees with per-page frontmatter stubs across all configured languages; propose dep-manifest pins and Taskfile docs target. Confirm per file before writing.
3. patch (additive: mkdocs.yml present)
For each missing or drift finding, propose the minimal fix and ask for per-item approval before writing. Patch mode is additive, never destructive. Re-run mkdocs build --strict after every successful write.
Output contract
The skill returns to the user, in this order:
- Operation + target: which operation ran (
audit / scaffold / patch), absolute target repo root, detected language list, detected active extension specs.
- Pre-state: brief summary of what was found (
mkdocs.yml present? per-language trees present? plugin baseline pinned? audience artifact present?).
- Audit findings (always): grouped per spec area (Site layout, Top-level navigation, Plugin baseline, Per-page structure, Content modes, Snippet inclusion, Site identity (
site_url), i18n parity, Build verification, Extension conformance, Cap check) — the same eleven groups the audit operation walks — with one row per Acceptance-Criteria item showing status (pass / missing / drift) and a one-line evidence snippet.
- Planned edits (for
scaffold / patch): list of files to create or modify, one line per file, with rationale linking back to the spec line.
- Approval gate (for
scaffold / patch): explicit user-decision point; nothing is written until the user confirms.
- Applied edits (after approval): list of files actually written, with absolute paths.
- Build verification:
mkdocs build --strict exit code plus a raw output snippet on failure; on success report the build summary line only.
- Caller follow-ups: explicit list — commit the working-tree edits, run the proposed
pip install / uv pip install / poetry add command to install the new baseline plugins, dispatch audience-doc-author to fill in the page content stubs, route to skill-agent-catalog-apply when the catalog extension is active and not yet wired, open the PR via pull-request-create, and similar.
Examples
- Read
examples/01-audit-conformance-report.md when running a read-only audit and you need the eleven-group findings table, including the critical missing-site_url case under multi-language i18n.
- Read
examples/02-scaffold-fresh-repo.md when mkdocs.yml is absent and you must scaffold the greenfield skeleton: derived site_url, baseline plugins, seven nav sections, symmetric per-language docs trees.
- Read
examples/03-patch-missing-site-url.md when mkdocs.yml is present and you must additively patch a single flagged finding (here site_url, honouring the CNAME custom-domain exception) with a post-write strict build.
Resumability
Per spec/claude/resumable-work/, this skill is resumable: true. State is persisted to .resume/mkdocs-structure-apply/<run-id>.yml after every successful user-approval gate and after each named phase boundary. On re-invocation, scan that directory for files with status: in_progress whose inputs: snapshot matches the current invocation; if one matches, prompt the operator with Resume run <run_id> from phase <phase> (last checkpoint <last_checkpoint_at>)? [resume / start-new / discard]. The state-file envelope (schema_version, run_id, inputs, phase, decisions[], status, ...) and the fail-closed semantics on schema or YAML errors are load-bearing in the spec; don't duplicate those rules here.
Hard rules
- Never modify theme palette, typography, or visual identity. These are per-repo decisions per
spec/project/mkdocs-structure/ §Non-Goals. The skill mandates mkdocs-material as the engine but never picks the colour scheme.
- Never author markdown page content. The skill creates the containers (section folders, index pages with frontmatter, H1, and placeholder paragraph), but never the prose body. Page-content authoring belongs to the
audience-doc-author agent or to the human author.
- Never silently override existing
mkdocs.yml decisions. When an existing config diverges from the spec baseline (a custom nav order, an extra plugin, a different theme variant), the skill surfaces the conflict, proposes the resolution, and waits for user approval. Patch mode is additive, not destructive.
- Always read the spec at runtime: prefer the target repo's
spec/project/mkdocs-structure/<canonical_language>.md; fall back to the copy shipped by the nolte-shared plugin (read from ${CLAUDE_PLUGIN_ROOT}/spec/project/mkdocs-structure/<canonical_language>.md) only when the target repo lacks one. Never carry a baked-in copy inside the skill itself; never invent requirements that don't appear in either reachable copy. When neither is reachable, stop and ask the user which spec source to use (matches the spec's own §Extension hooks §"Project-type discovery" fallback pattern).
- Always run
mkdocs build --strict after every non-trivial edit. The build is the authoritative rendering gate; a passing local build is the floor, not the ceiling. Failures stop the skill and surface the raw output to the user.
- Never bump versions, commit, push, tag releases, or open pull requests. The skill produces working-tree edits only; commit / PR / release lifecycle is owned by separate skills (
pull-request-create, pull-request-merge, release-publish-trigger).
- Never install Python packages on the caller's machine. When a baseline plugin is missing from the dep manifest, the skill reports the exact
pip install / uv pip install / poetry add command appropriate to the project's package manager; the user runs it.
- Never dispatch the
Skill tool recursively into this skill (silent loops) or chain to a sibling skill outside the declared hand-off points. The skill MAY orchestrate the audience-doc-author agent and the docs-dry-refactor skill at the explicit hand-off points named in the Output contract Caller follow-ups section; orchestration is allowed per spec/claude/skill-vs-agent/ §Hybrid pattern, silent recursion isn't.
- Never create or modify GitHub labels, branch protections, or remote state. The skill is local-only; remote state is owned by
project-structure-apply and the platform Probot configs.
- Plugin-extension MUSTs from project-type-specific extension specs are additive. The skill reads every active extension spec (discoverable via marker files per the parent spec's §Extension hooks §"Project-type discovery"), composes their MUSTs with the baseline, and emits a combined audit. The skill never silently relaxes a baseline MUST because an extension is active; explicit relaxation requires a stated rationale in the extension spec.
- Never duplicate the catalog-generator wiring owned by
skill-agent-catalog-apply. When the catalog extension is active, route the user to that skill for the gen-files + literate-nav plumbing; this skill only verifies the catalog extension's MUSTs are honoured at the baseline level.
- Never rename, reorder, or hide a standard section silently. The seven-section order is fixed by the spec; reordering is a spec amendment, not a patch.
- Always scaffold every container page (section folder index pages, placeholder pages with frontmatter) symmetrically across every language tree configured in
spec/.spec-config.yml's languages list, per spec/project/docs-multilingual-authoring/ §Authoring protocol. Writing docs/<canonical_language>/<section>/index.md without writing the counterparts in every other configured language tree in the same operation is a violation, even when the page body is a placeholder. README.md at the repository root is the explicit exception per spec/project/readme-structure/ §File and language and stays English-only.
Gotchas
Per spec/claude/skill-management/ §Gotchas: concrete corrections to non-obvious environment facts the executing agent would otherwise get wrong.
mkdocs-static-i18n with docs_structure: folder requires every page to exist in every configured language tree. A docs/de/index.md without a matching docs/en/index.md (or vice versa) is a build-time error, not a warning. When scaffolding for a new language, scaffold the full file tree at once rather than one page at a time; partial scaffolds break the build.
- The built-in
search plugin must be declared explicitly in the plugins: list once any other plugin is declared. MkDocs's default behaviour is to enable search when plugins: is absent; declaring any plugin disables the default and requires search to be listed explicitly. Forgetting this is a common silent regression that drops the site's search bar.
pymdownx.superfences belongs in markdown_extensions:, not plugins:. It's a Markdown extension shipped by pymdown-extensions, not a MkDocs plugin. Misplacing it produces an opaque build error that points at the wrong line.
mkdocs-include-markdown-plugin resolves include paths relative to the docs_dir, not relative to the file that contains the include directive. A {% include-markdown "../../../README.md" %} from docs/en/guides/intro.md works because MkDocs walks up from docs/, not from the page file. Be explicit about the path origin when generating include directives so the user doesn't get confused.
spec/.spec-config.yml's languages list is the source of truth for the configured language set, not mkdocs.yml's i18n plugin config. When the two diverge, treat spec/.spec-config.yml as authoritative and surface the divergence; never mutate spec/.spec-config.yml from this skill.
- The package manager detection is order-sensitive. Check for
uv.lock before poetry.lock before requirements*.txt before falling back to a bare pyproject.toml [project.dependencies]; the presence of a lock file is a stronger signal than the bare manifest and dictates the install command to recommend.
site_url is derived from the repository's coordinates, never guessed. Read repo_url from mkdocs.yml; fall back to git remote get-url origin. The default is the GitHub-Pages project-site subpath https://<owner>.github.io/<repo>/ (mind the trailing slash). Three exceptions the derivation MUST honour before proposing a value: (1) a repository named <owner>.github.io is an org/user-pages site that publishes at the root https://<owner>.github.io/ with no subpath; (2) a CNAME file under the repo root or docs/ means the site is served under a custom domain — use that domain, not the github.io path; (3) when neither signal is conclusive, propose the derived value and ask the user to confirm rather than writing silently (Hard rule 3). The breakage this fixes is the absence of site_url (mkdocs-static-i18n then falls back to / and emits wrong absolute switcher/hreflang links on a project subpath); a present-but-slashless value still renders correctly, so the trailing slash is a SHOULD, not a build-breaking MUST.
mkdocs build --strict fails on every warning, not just errors. A missing language-tree counterpart, a broken include marker, an unreferenced page in nav:, all trip the strict flag. When the build fails, surface the entire stderr block verbatim; the line numbers in MkDocs output are load-bearing for the user's fix.
- The five-extension-section cap (per spec §Extension hooks) is summed across every active extension spec. A repo activating two extension specs that each declare three sections is over the cap by one; the skill surfaces this as a Critical finding and routes the user to consolidate or amend the spec, never silently truncating.
1---2name: mkdocs-structure-apply3description: Audits a repository against the canonical-language file under spec/project/mkdocs-structure/ and, with per-item user approval, scaffolds or patches the MkDocs skeleton: the per-language docs/ tree, seven standard nav sections, plugin baseline (incl. mkdocs-include-markdown-plugin), required `site_url`, pinned dep manifest, per-page frontmatter contract. Three operations: `audit` (read-only conformance report), `scaffold` (greenfield), `patch` (additive fixes). Invoke when the user asks to apply, audit, scaffold, or patch MkDocs against the spec; also handles equivalent German-language requests. Don't use for theme/typography decisions (per-repo), page-content authoring (use `audience-doc-author`), DRY refactoring (use `docs-dry-refactor`), per-page track frontmatter or audience-track content blocks (use `docs-audience-tracks-apply`), drift detection (use `docs-freshness-checker`), or catalog generator wiring (use `skill-agent-catalog-apply`). Supports resume on re-invocation per `spec/claude/resumable-work/`.4---56# MkDocs Structure Apply78Operationalises `spec/project/mkdocs-structure/<canonical_language>.md` inside the current repository. The skill audits the current MkDocs wiring against the baseline plus every active project-type-specific extension spec, proposes the concrete file-level changes the spec requires, and—with explicit per-item user consent—applies them.910When the spec isn't present in the target repository, fall back to the copy shipped by the `nolte-shared` plugin (read it at runtime from `${CLAUDE_PLUGIN_ROOT}/spec/project/mkdocs-structure/<canonical_language>.md`). Never invent requirements that don't appear in the spec.1112## Why this is a skill, not an agent1314Per `spec/claude/skill-vs-agent/` §Decision dimensions, this capability is a skill because:1516- **Mid-flow user approval is the contract.** Every scaffold or patch decision (mkdocs.yml plugin additions, docs/<lang>/ section folders, dep-manifest pins, Taskfile wiring) is written only with explicit per-change confirmation; the audit is read-only and the apply step is a sequence of approvals an agent's fire-and-forget shape can't carry.17- **Persistent on-disk output that flows back into the main conversation.** The audit table, the per-item proposals, and the build-verification output all surface in the conversation so the user can decide; isolating them in a structured-report boundary would obscure the per-file approval surface.18- **Orchestrator pattern.** The skill can dispatch the `audience-doc-author` agent for page-content authoring or the `docs-dry-refactor` skill for DRY refactoring; per `spec/claude/skill-vs-agent/` §Hybrid pattern, the orchestrator is always a skill.19- **Precedent.** Follows the same audit + scaffold + patch shape as `project-structure-apply` and `skill-agent-catalog-apply`; portfolio-wide consistency (`spec/claude/skill-vs-agent/` §Portfolio-wide consistency) favours the same artifact type.20- **Counter-dimension considered.** A narrower agent could specialise on mkdocs.yml-patch generation and gain on context-window protection, but the high-impact part is the per-item approval dialogue and the build-verification loop, not the boilerplate generation; skill wins.2122## User-language policy2324Detect the user's language from their message and respond in it. Generated file contents (`mkdocs.yml`, `docs/<lang>/index.md`, section index stubs, dep-manifest patches, `Taskfile.yml` targets) are always written in English so portfolio-wide automation stays predictable. Comments inside generated files are English as well.2526## Tools used2728Tools this skill uses: `Read`, `Write`, `Edit`, `Glob`, `Grep`, `Bash`.2930- `Read` / `Glob` / `Grep` for repository inspection (mkdocs.yml, docs/<lang>/ trees, dep manifests, page frontmatter, active extension-spec markers).31- `Write` / `Edit` for scaffold and patch operations on `mkdocs.yml`, docs trees, and dep manifests; never overwriting existing config wholesale.32- `Bash` is necessary for `mkdocs build --strict` verification, `task docs` local invocation, and detecting the project's package manager (`pyproject.toml` shape, `uv.lock` / `poetry.lock` / `requirements*.txt` presence). The skill never runs destructive bash (`git push`, `gh pr create`, `pip install`, `rm -rf`).33- No `WebFetch` / `WebSearch`: the spec is the only source of truth; baseline plugin pins are read from the project's existing dep manifest, never from the network.3435## Preconditions3637Before doing anything:38391. Confirm the working directory is a git repository (`git rev-parse --is-inside-work-tree`).402. Locate `spec/project/mkdocs-structure/<canonical_language>.md`—either in the target repo or via the `nolte-shared` plugin. If neither is reachable, stop and ask the user which spec source to use (matches the spec's §Extension hooks §"Project-type discovery" fallback pattern).413. Determine the operation:42 - If `mkdocs.yml` is absent → `scaffold` (default).43 - If `mkdocs.yml` is present → `patch` (or `audit` when the user explicitly asks for a read-only conformance check).444. Detect active extension specs by scanning marker files at the repo root: `.claude-plugin/plugin.json` activates `spec/claude/skill-agent-catalog/`; `cookiecutter.json` plus `{{cookiecutter.project_slug}}/` activates a future cookiecutter-template-docs spec; and so on. Read every active extension spec at runtime; compose its MUSTs additively with the baseline (per the spec's §Extension hooks rule "every active extension's MUSTs are additive to the baseline MUSTs").455. Resolve the language list from `spec/.spec-config.yml` `languages`. If that file is absent, ask the user which languages the docs should ship in; default to a single `en` only after explicit confirmation.466. Check for uncommitted changes in `mkdocs.yml`, `docs/`, the dep manifest, and `Taskfile.yml`. If the tree is dirty there, report and ask whether to stash, commit, or abort—never overwrite uncommitted work.4748## Operations4950Read `references/operations.md` when executing any of the operations below in detail.5152### 1. `audit` (read-only)5354Walk the spec's Acceptance Criteria and every active extension spec's MUSTs; classify each finding as `pass`, `missing`, or `drift` grouped by spec area (Site layout, Top-level navigation, Plugin baseline, Per-page structure, Content modes, Snippet inclusion, Site identity (`site_url`), i18n parity, Build verification, Extension conformance, Cap check). The Site-identity check reports a `missing` finding when `site_url` is absent and a `drift` finding when it doesn't match the repository's published base URL; when `mkdocs-static-i18n` declares more than one language, treat a missing `site_url` as critical. Audit is read-only—never autofix.5556### 2. `scaffold` (greenfield: `mkdocs.yml` absent)5758Create `mkdocs.yml` with Material theme, baseline plugins (`search`, `i18n`, `include-markdown`), `site_url` derived from the repository's coordinates (see Gotchas for the derivation rule), seven standard nav sections, and `nav_translations` skeleton; scaffold `docs/<lang>/` trees with per-page frontmatter stubs across all configured languages; propose dep-manifest pins and Taskfile `docs` target. Confirm per file before writing.5960### 3. `patch` (additive: `mkdocs.yml` present)6162For each `missing` or `drift` finding, propose the minimal fix and ask for per-item approval before writing. Patch mode is additive, never destructive. Re-run `mkdocs build --strict` after every successful write.6364## Output contract6566The skill returns to the user, in this order:67681. **Operation + target**: which operation ran (`audit` / `scaffold` / `patch`), absolute target repo root, detected language list, detected active extension specs.692. **Pre-state**: brief summary of what was found (`mkdocs.yml` present? per-language trees present? plugin baseline pinned? audience artifact present?).703. **Audit findings** (always): grouped per spec area (Site layout, Top-level navigation, Plugin baseline, Per-page structure, Content modes, Snippet inclusion, Site identity (`site_url`), i18n parity, Build verification, Extension conformance, Cap check) — the same eleven groups the `audit` operation walks — with one row per Acceptance-Criteria item showing status (`pass` / `missing` / `drift`) and a one-line evidence snippet.714. **Planned edits** (for `scaffold` / `patch`): list of files to create or modify, one line per file, with rationale linking back to the spec line.725. **Approval gate** (for `scaffold` / `patch`): explicit user-decision point; nothing is written until the user confirms.736. **Applied edits** (after approval): list of files actually written, with absolute paths.747. **Build verification**: `mkdocs build --strict` exit code plus a raw output snippet on failure; on success report the build summary line only.758. **Caller follow-ups**: explicit list — commit the working-tree edits, run the proposed `pip install` / `uv pip install` / `poetry add` command to install the new baseline plugins, dispatch `audience-doc-author` to fill in the page content stubs, route to `skill-agent-catalog-apply` when the catalog extension is active and not yet wired, open the PR via `pull-request-create`, and similar.7677## Examples7879- Read `examples/01-audit-conformance-report.md` when running a read-only `audit` and you need the eleven-group findings table, including the critical missing-`site_url` case under multi-language i18n.80- Read `examples/02-scaffold-fresh-repo.md` when `mkdocs.yml` is absent and you must `scaffold` the greenfield skeleton: derived `site_url`, baseline plugins, seven nav sections, symmetric per-language docs trees.81- Read `examples/03-patch-missing-site-url.md` when `mkdocs.yml` is present and you must additively `patch` a single flagged finding (here `site_url`, honouring the `CNAME` custom-domain exception) with a post-write strict build.8283## Resumability8485Per `spec/claude/resumable-work/`, this skill is `resumable: true`. State is persisted to `.resume/mkdocs-structure-apply/<run-id>.yml` after every successful user-approval gate and after each named phase boundary. On re-invocation, scan that directory for files with `status: in_progress` whose `inputs:` snapshot matches the current invocation; if one matches, prompt the operator with `Resume run <run_id> from phase <phase> (last checkpoint <last_checkpoint_at>)? [resume / start-new / discard]`. The state-file envelope (`schema_version`, `run_id`, `inputs`, `phase`, `decisions[]`, `status`, ...) and the fail-closed semantics on schema or YAML errors are load-bearing in the spec; don't duplicate those rules here.8687## Hard rules88891. **Never** modify theme palette, typography, or visual identity. These are per-repo decisions per `spec/project/mkdocs-structure/` §Non-Goals. The skill mandates `mkdocs-material` as the engine but never picks the colour scheme.902. **Never** author markdown page content. The skill creates the *containers* (section folders, index pages with frontmatter, H1, and placeholder paragraph), but never the prose body. Page-content authoring belongs to the `audience-doc-author` agent or to the human author.913. **Never** silently override existing `mkdocs.yml` decisions. When an existing config diverges from the spec baseline (a custom nav order, an extra plugin, a different theme variant), the skill surfaces the conflict, proposes the resolution, and waits for user approval. Patch mode is additive, not destructive.924. **Always** read the spec at runtime: prefer the target repo's `spec/project/mkdocs-structure/<canonical_language>.md`; fall back to the copy shipped by the `nolte-shared` plugin (read from `${CLAUDE_PLUGIN_ROOT}/spec/project/mkdocs-structure/<canonical_language>.md`) only when the target repo lacks one. Never carry a baked-in copy inside the skill itself; never invent requirements that don't appear in either reachable copy. When neither is reachable, stop and ask the user which spec source to use (matches the spec's own §Extension hooks §"Project-type discovery" fallback pattern).935. **Always** run `mkdocs build --strict` after every non-trivial edit. The build is the authoritative rendering gate; a passing local build is the floor, not the ceiling. Failures stop the skill and surface the raw output to the user.946. **Never** bump versions, commit, push, tag releases, or open pull requests. The skill produces working-tree edits only; commit / PR / release lifecycle is owned by separate skills (`pull-request-create`, `pull-request-merge`, `release-publish-trigger`).957. **Never** install Python packages on the caller's machine. When a baseline plugin is missing from the dep manifest, the skill reports the exact `pip install` / `uv pip install` / `poetry add` command appropriate to the project's package manager; the user runs it.968. **Never** dispatch the `Skill` tool recursively into this skill (silent loops) or chain to a sibling skill outside the declared hand-off points. The skill **MAY** orchestrate the `audience-doc-author` agent and the `docs-dry-refactor` skill at the explicit hand-off points named in the Output contract `Caller follow-ups` section; orchestration is allowed per `spec/claude/skill-vs-agent/` §Hybrid pattern, silent recursion isn't.979. **Never** create or modify GitHub labels, branch protections, or remote state. The skill is local-only; remote state is owned by `project-structure-apply` and the platform Probot configs.9810. **Plugin-extension MUSTs from project-type-specific extension specs are additive.** The skill reads every active extension spec (discoverable via marker files per the parent spec's §Extension hooks §"Project-type discovery"), composes their MUSTs with the baseline, and emits a combined audit. The skill never silently relaxes a baseline MUST because an extension is active; explicit relaxation requires a stated rationale in the extension spec.9911. **Never** duplicate the catalog-generator wiring owned by `skill-agent-catalog-apply`. When the catalog extension is active, route the user to that skill for the `gen-files` + `literate-nav` plumbing; this skill only verifies the catalog extension's MUSTs are honoured at the baseline level.10012. **Never** rename, reorder, or hide a standard section silently. The seven-section order is fixed by the spec; reordering is a spec amendment, not a patch.10113. **Always** scaffold every container page (section folder index pages, placeholder pages with frontmatter) symmetrically across every language tree configured in `spec/.spec-config.yml`'s `languages` list, per `spec/project/docs-multilingual-authoring/` §Authoring protocol. Writing `docs/<canonical_language>/<section>/index.md` without writing the counterparts in every other configured language tree in the same operation is a violation, even when the page body is a placeholder. `README.md` at the repository root is the explicit exception per `spec/project/readme-structure/` §File and language and stays English-only.102103## Gotchas104105Per `spec/claude/skill-management/` §Gotchas: concrete corrections to non-obvious environment facts the executing agent would otherwise get wrong.106107- **`mkdocs-static-i18n` with `docs_structure: folder` requires every page to exist in every configured language tree.** A `docs/de/index.md` without a matching `docs/en/index.md` (or vice versa) is a build-time error, not a warning. When scaffolding for a new language, scaffold the full file tree at once rather than one page at a time; partial scaffolds break the build.108- **The built-in `search` plugin must be declared explicitly in the `plugins:` list once any other plugin is declared.** MkDocs's default behaviour is to enable `search` when `plugins:` is absent; declaring any plugin disables the default and requires `search` to be listed explicitly. Forgetting this is a common silent regression that drops the site's search bar.109- **`pymdownx.superfences` belongs in `markdown_extensions:`, not `plugins:`.** It's a Markdown extension shipped by `pymdown-extensions`, not a MkDocs plugin. Misplacing it produces an opaque build error that points at the wrong line.110- **`mkdocs-include-markdown-plugin` resolves include paths relative to the `docs_dir`, not relative to the file that contains the include directive.** A `{% include-markdown "../../../README.md" %}` from `docs/en/guides/intro.md` works because MkDocs walks up from `docs/`, not from the page file. Be explicit about the path origin when generating include directives so the user doesn't get confused.111- **`spec/.spec-config.yml`'s `languages` list is the source of truth for the configured language set, not `mkdocs.yml`'s `i18n` plugin config.** When the two diverge, treat `spec/.spec-config.yml` as authoritative and surface the divergence; never mutate `spec/.spec-config.yml` from this skill.112- **The package manager detection is order-sensitive.** Check for `uv.lock` before `poetry.lock` before `requirements*.txt` before falling back to a bare `pyproject.toml` `[project.dependencies]`; the presence of a lock file is a stronger signal than the bare manifest and dictates the install command to recommend.113- **`site_url` is derived from the repository's coordinates, never guessed.** Read `repo_url` from `mkdocs.yml`; fall back to `git remote get-url origin`. The default is the GitHub-Pages project-site subpath `https://<owner>.github.io/<repo>/` (mind the trailing slash). Three exceptions the derivation MUST honour before proposing a value: (1) a repository named `<owner>.github.io` is an org/user-pages site that publishes at the root `https://<owner>.github.io/` with no subpath; (2) a `CNAME` file under the repo root or `docs/` means the site is served under a custom domain — use that domain, not the github.io path; (3) when neither signal is conclusive, propose the derived value and ask the user to confirm rather than writing silently (Hard rule 3). The breakage this fixes is the **absence** of `site_url` (mkdocs-static-i18n then falls back to `/` and emits wrong absolute switcher/`hreflang` links on a project subpath); a present-but-slashless value still renders correctly, so the trailing slash is a SHOULD, not a build-breaking MUST.114- **`mkdocs build --strict` fails on every warning, not just errors.** A missing language-tree counterpart, a broken include marker, an unreferenced page in `nav:`, all trip the strict flag. When the build fails, surface the entire stderr block verbatim; the line numbers in MkDocs output are load-bearing for the user's fix.115- **The five-extension-section cap (per spec §Extension hooks) is summed across every active extension spec.** A repo activating two extension specs that each declare three sections is over the cap by one; the skill surfaces this as a Critical finding and routes the user to consolidate or amend the spec, never silently truncating.