From 4d548099d61205cbae66eb92bd275967aef23e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 8 May 2026 10:55:47 +0200 Subject: [PATCH 01/19] Convert CONTRIBUTING.md to AI skill for contribution validation CONTRIBUTING.md is now a symlink to a skill file that serves dual purposes: - Human-readable contribution guidelines (visible on GitHub) - AI-invocable validation skill via /validate-contribution The skill validates and auto-fixes common issues in documentation contributions: - Trailing whitespace removal - File naming conventions (con_, proc_, ref_, snip_ prefixes) - Content type attributes - Module ID format with {context} - Hardcoded product names replaced with attributes - Vale linter integration - Build verification Contributors can run /validate-contribution manually to check their changes before submitting PRs. Co-Authored-By: Claude Sonnet 4.5 --- .cursor/skills/validate-contribution/SKILL.md | 290 ++++++++++++++++++ CONTRIBUTING.md | 207 +------------ 2 files changed, 291 insertions(+), 206 deletions(-) create mode 100644 .cursor/skills/validate-contribution/SKILL.md mode change 100644 => 120000 CONTRIBUTING.md diff --git a/.cursor/skills/validate-contribution/SKILL.md b/.cursor/skills/validate-contribution/SKILL.md new file mode 100644 index 00000000000..3e01dd7d58b --- /dev/null +++ b/.cursor/skills/validate-contribution/SKILL.md @@ -0,0 +1,290 @@ +--- +name: validate-contribution +description: Validate and auto-fix documentation contributions against project guidelines +disable-model-invocation: false +--- +# Contributing to Foreman Documentation + +If you need help to get started, open an issue, ask the docs team on [Matrix](https://matrix.to/#/#theforeman-doc:matrix.org), or ping [`@docs`](https://community.theforeman.org/g/docs) on the [Foreman Community Forum](https://community.theforeman.org/). + +## Contributor's pledge + +As a contributor, I will: + +* Familiarize myself with the [Pull Request Checklist](#Pull-Request-Checklist) and [Foreman documentation conventions guide](#Foreman-documentation-conventions-guide). +* Open additional issues if my contribution is incomplete. +* Put in my best effort to ensure that my contribution does not worsen the state of any build target. +For example, this might include reviewing how my changes affect upstream build targets even when working on behalf of a downstream product. + +## Maintainer's pledge + +As a maintainer, I will: + +* Help less experienced community members with git, Github, PRs, asciidoc, and asciidoctor and make friendly and helpful comments. +* Only merge PRs if the Github Actions are green. +* Try to review PRs in a timely manner. +* Keep non-trivial PRs open for at least 24 hours (72 hours if over the weekend) to allow for input from the community. +Examples of trivial PRs: Fixing a typo, fixing markup, or fixing links. +Non-trivial PRs might not only benefit from additional review but they also represent an opportunity for community members to ask questions and learn. + +## Pull request checklists + +Checklist for documentation contributions: + +* [ ] My contribution is my own work and I agree to the license of the project. +See [LICENSE](LICENSE). +* [ ] My commits include meaningful commit messages. +See [seven rules for git commit messages](https://cbea.ms/git-commit/#seven-rules). +* [ ] My change does not add trailing whitespaces. +Some editors can help with this. +For example, VS Code has multiple settings related to handling whitespaces. + +Checklist for raising PRs: + +* [ ] I re-read my work carefully before raising a PR or before marking a draft PR as ready for review. +This can include using `git show`, viewing the diff against master or the target branch, running a local Vale check, and other methods. +* [ ] My PR description includes a meaningful description of the changes for the community. +* [ ] I fill out the cherry-picking list in the PR description to the best of my abilities to signify which versions my update applies to. +If unsure, I let reviewers know so that they can assist. +* [ ] Before pinging others about my PR, I await the GitHub Actions checks to see if my branch builds. +If a GitHub check fails and I'm unsure how to proceed, I let reviewers know so that they can assist. + +Each PR should undergo tech review. +(Tech review is performed by an Engineer who did not author the PR. It can be skipped if the PR does not significantly change description of product behavior.) + +* [ ] The PR documents a recommended, user-friendly path. +* [ ] The PR removes steps that have been made unnecessary or obsolete. +* [ ] Any steps introduced or updated in the PR have been tested to confirm that they lead to the documented end result. + +Each PR should undergo style review. +(Style review is performed by a Technical Writer who did not author the PR.) + +* [ ] The PR conforms with the team's style guidelines. +* [ ] The PR introduces documentation that describes a user story rather than a product feature. + +## Foreman documentation conventions guide + +The `Foreman documentation conventions guide` describes guidelines specific to working on Foreman documentation. +It complements, but should not duplicate, the following resources: + +* The AsciiDoc, RedHat, and project-specific foreman-documentation style packages for the Vale linter. +See [Vale for writers at Red Hat](https://redhat-documentation.github.io/vale-at-red-hat/docs/main/user-guide/introduction/). +* [Red Hat supplementary style guide for product documentation](https://redhat-documentation.github.io/supplementary-style-guide/) + +### Code conventions + +Use the following markup conventions: + +* Use UTF-8 character encoding in source files. +* Do not add trailing whitespace on lines and in files. +Some editors can help with this. +For example, VS Code has multiple settings related to handling whitespaces. +Whitespace after partial files has to be handled in the file using the `include::` directive. +* Surround user input with underscores (`_`) to indicate variable input, for example, `hammer organization create --name "_My_Organization_"`. + +### Images + +Each guide directory contains an `images/` subdirectory with `images/common` symlink into the `common/images/` directory. + +* Save images local to the guide to the `images/` directory. +* Save images which are supposed to be reused across guides to the `images/common/` directory. + +You can create upstream diagrams using [diagrams.net](https://www.diagrams.net/). +Place the editable diagram in `drawio` format in `guides/image-sources/`. +For inclusion in the content, export diagrams to SVG and place them as described above. + +### AsciiDoc attributes for different build targets + +Because the content in this repository is shared between the upstream Foreman community and branded downstream products, many terms need to be written using AsciiDoc attributes. +For example, never write "Foreman", "Satellite", or "orcharhino" words directly, but use the `{Project}` attribute. + +The attributes used in this repository are defined in the following files: + +* [attributes.adoc](common/attributes.adoc): version definitions and includes for other attribute files. +* [attributes-base.adoc](common/attributes-base.adoc): base attributes common for all builds. +* [attributes-foreman-el.adoc](common/attributes-foreman-el.adoc): base overrides for foreman-el build. +* [attributes-foreman-deb.adoc](common/attributes-foreman-deb.adoc): base overrides for foreman-deb build. +* [attributes-katello.adoc](common/attributes-katello.adoc): base overrides for katello build. +* [attributes-satellite.adoc](common/attributes-satellite.adoc): base overrides for satellite build. +* [attributes-orcharhino.adoc](common/attributes-orcharhino.adoc): base overrides for orcharhino build. + +By default, attributes cannot be used in shell or code examples. +To use them, use the "attributes" keyword: + + [options="nowrap" subs="+quotes,attributes"] + ---- + # ls {AttributeName} + ---- + +### Conditional content + +If a piece of your content, such as a block, paragraph, warning, or chapter, is specific for a certain build target, use AsciiDoc conditionals to show or hide it. + +To show a piece of content only for the `katello` build: + + ifdef::katello[] + NOTE: This part is only relevant for Foreman with the Katello plugin. + endif::[] + +To hide a piece of content for `katello` but show it for all other builds: + + ifndef::katello[] + NOTE: This part is relevant for Foreman without the Katello plugin, but also Satellite and orcharhino. + endif::[] + +Use comma for logic "or": + + ifdef::katello,satellite[] + NOTE: This part is only relevant for deployments with Katello plugin or in Satellite environment. + endif::[] + +Some files are included in different contexts, there are attributes to find the correct context. +In these cases use both `ifdef` and `ifeval`: + + ifdef::foreman-el,foreman-deb[] + ifeval::["{context}" == "{project-context}"] + * A minimum of 4 GB RAM is required for {ProjectServer} to function. + endif::[] + endif::[] + +### File structure + +If you create a new file, use the file structure described here. + +Documentation in this directory follows a modular structure described in the [Modular documentation reference guide](https://redhat-documentation.github.io/modular-docs/). +To write new documentation, you can use [modular documentation templates](https://github.com/redhat-documentation/modular-docs/tree/main/modular-docs-manual/files) or copy an existing file from `guides/common/modules/` and adapt it. + +Included files are kept in the `common/` subdirectory and have prefixes to distinguish their type of content. + +Assemblies are kept at the top of the `common/` subdirectory: + +* [`assembly`](https://redhat-documentation.github.io/modular-docs/#forming-assemblies): Files starting with `assembly_` contain user stories and the modules required to accomplish those user stories. +See the [assembly template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_ASSEMBLY_a-collection-of-modules.adoc). + +Modules are kept in the `common/modules/` subdirectory: + +* [`con`](https://redhat-documentation.github.io/modular-docs/#creating-concept-modules): Files starting with `con_` contain concepts and explain the _what_ and _why_. +Their first line contains the `:_mod-docs-content-type: CONCEPT` attribute. +See the [concept template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_CONCEPT_concept-explanation.adoc). +* [`proc`](https://redhat-documentation.github.io/modular-docs/#creating-procedure-modules): Files starting with `proc_` contain procedures and explain _how_ to achieve a specific goal. +Their first line contains the `:_mod-docs-content-type: PROCEDURE` attribute. +See the [procedure template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_PROCEDURE_doing-one-procedure.adoc). +* [`ref`](https://redhat-documentation.github.io/modular-docs/#creating-reference-modules): Files starting with `ref_` contain references and append other files, for example tables with options. +Their first line contains the `:_mod-docs-content-type: REFERENCE` attribute. +See the [reference template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_REFERENCE_reference-material.adoc). +* [`snip`](https://redhat-documentation.github.io/modular-docs/#using_text_snippets_or_text_fragments_writing-mod-docs): Files starting with `snip_` contain snippets that are reused throughout multiple guides, for example admonitions. +Snippets must not contain an ID. + +### Foreman user personas + +In documentation, a user persona is the target user who will be reading the documentation. +Understanding and identifying the target persona of a piece of content helps ensure that the documentation will properly address the user's needs and capabilities. + +Foreman users include people with varying responsibilities and permissions. +Especially in larger organizations, different tasks are performed by different teams. +Therefore, when contributing to Foreman documentation, it can be useful to be aware of and distinguish Foreman user personas. + +#### *User* persona + +* Has limited permissions +* Runs regular Foreman operations +* Example responsibilities: managing content, provisioning hosts, and managing hosts + +#### *Admin* persona + +* Has unlimited permissions, including root access to the Foreman Server +* Example responsibilities: managing Foreman server + +#### *Architect* persona + +* Has no permissions, does not perform practical administrative or management tasks +* Example responsibilities: determining whether Foreman/Katello meets the needs of their organization and planning the deployment + +### Further Information + +* [Contributing Guidelines for Github documentation](https://github.com/github/docs/blob/main/CONTRIBUTING.md) +* [theforeman.org/contribute](https://theforeman.org/contribute.html) +* [7 Git tips for technical writers](https://opensource.com/article/22/11/git-tips-technical-writers) + +--- + +## AI Instructions: Automatic Validation and Fixing + +When invoked (either manually or automatically after AI makes changes), perform the following checks and auto-fixes on all modified `.adoc` files in `guides/`: + +### 1. File Naming Validation + +**Check**: Files in `guides/common/modules/` must have correct prefixes: +- `con_*.adoc` - Concept modules +- `proc_*.adoc` - Procedure modules +- `ref_*.adoc` - Reference modules +- `snip_*.adoc` - Snippets + +**Auto-fix**: If prefix doesn't match content type attribute, rename the file and update all includes. + +### 2. Content Type Attribute + +**Check**: All modules (except snippets) must have content type on first line: +- `:_mod-docs-content-type: CONCEPT` +- `:_mod-docs-content-type: PROCEDURE` +- `:_mod-docs-content-type: REFERENCE` + +**Auto-fix**: Add missing content type attribute based on file prefix. + +### 3. Module ID Format + +**Check**: All modules (except snippets) must have ID in format `[id="title-with-dashes_{context}"]` + +**Auto-fix**: Add or fix ID to match title and include `_{context}` suffix. + +### 4. Trailing Whitespace + +**Check**: No trailing whitespace on any lines or at end of files. + +**Auto-fix**: Remove all trailing whitespace. + +### 5. Hardcoded Product Names + +**Check**: Scan for hardcoded product names that should use attributes: +- "Foreman" → `{Project}` or `{ProjectName}` +- "Satellite" → `{Project}` (in multi-build contexts) +- "orcharhino" → `{Project}` (in multi-build contexts) +- "Capsule" → `{SmartProxy}` or `{SmartProxyServer}` + +**Auto-fix**: Replace with appropriate attribute if found in non-conditional context. + +### 6. Vale Linting + +**Check**: Run `vale` on modified files. + +**Report**: List any style violations (don't auto-fix Vale issues, just report them). + +### 7. Build Test + +**Check**: Ensure modified files can build successfully. + +**Report**: If build fails, show error and affected files. + +### Output Format + +After validation and fixes, provide a concise summary: + +``` +✅ Validated contribution +Fixed: + - Removed trailing whitespace from 3 files + - Added content type attribute to proc_example.adoc + - Fixed ID format in con_overview.adoc + +⚠ Warnings: + - Vale: 2 style issues in proc_example.adoc (lines 15, 23) + +✓ Build: All modified files build successfully +``` + +### When NOT to Run + +Skip validation if: +- Changes are only to non-documentation files (Makefiles, scripts, config) +- Changes are only to `web/` directory +- Changes are to this CONTRIBUTING.md file itself diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index c5ad79998df..00000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,206 +0,0 @@ -# Contributing to Foreman Documentation - -If you need help to get started, open an issue, ask the docs team on [Matrix](https://matrix.to/#/#theforeman-doc:matrix.org), or ping [`@docs`](https://community.theforeman.org/g/docs) on the [Foreman Community Forum](https://community.theforeman.org/). - -## Contributor's pledge - -As a contributor, I will: - -* Familiarize myself with the [Pull Request Checklist](#Pull-Request-Checklist) and [Foreman documentation conventions guide](#Foreman-documentation-conventions-guide). -* Open additional issues if my contribution is incomplete. -* Put in my best effort to ensure that my contribution does not worsen the state of any build target. -For example, this might include reviewing how my changes affect upstream build targets even when working on behalf of a downstream product. - -## Maintainer's pledge - -As a maintainer, I will: - -* Help less experienced community members with git, Github, PRs, asciidoc, and asciidoctor and make friendly and helpful comments. -* Only merge PRs if the Github Actions are green. -* Try to review PRs in a timely manner. -* Keep non-trivial PRs open for at least 24 hours (72 hours if over the weekend) to allow for input from the community. -Examples of trivial PRs: Fixing a typo, fixing markup, fixing links, updating release version configuration files (e.g., `web/releases/*.json`). -Time-critical release changes, such as release notes, can be merged without waiting 24 hours, but still require peer review and an ACK. -Non-trivial PRs might not only benefit from additional review but they also represent an opportunity for community members to ask questions and learn. -All PRs, including trivial ones, require peer review and an ACK before merging. - -## Pull request checklists - -Checklist for documentation contributions: - -* [ ] My contribution is my own work and I agree to the license of the project. -See [LICENSE](LICENSE). -* [ ] My commits include meaningful commit messages. -See [seven rules for git commit messages](https://cbea.ms/git-commit/#seven-rules). -* [ ] My change does not add trailing whitespaces. -Some editors can help with this. -For example, VS Code has multiple settings related to handling whitespaces. - -Checklist for raising PRs: - -* [ ] I re-read my work carefully before raising a PR or before marking a draft PR as ready for review. -This can include using `git show`, viewing the diff against master or the target branch, running a local Vale check, and other methods. -* [ ] My PR description includes a meaningful description of the changes for the community. -* [ ] I fill out the cherry-picking list in the PR description to the best of my abilities to signify which versions my update applies to. -If unsure, I let reviewers know so that they can assist. -* [ ] Before pinging others about my PR, I await the GitHub Actions checks to see if my branch builds. -If a GitHub check fails and I'm unsure how to proceed, I let reviewers know so that they can assist. - -Each PR should undergo tech review. -(Tech review is performed by an Engineer who did not author the PR. It can be skipped if the PR does not significantly change description of product behavior.) - -* [ ] The PR documents a recommended, user-friendly path. -* [ ] The PR removes steps that have been made unnecessary or obsolete. -* [ ] Any steps introduced or updated in the PR have been tested to confirm that they lead to the documented end result. - -Each PR should undergo style review. -(Style review is performed by a Technical Writer who did not author the PR.) - -* [ ] The PR conforms with the team's style guidelines. -* [ ] The PR introduces documentation that describes a user story rather than a product feature. - -## Foreman documentation conventions guide - -The `Foreman documentation conventions guide` describes guidelines specific to working on Foreman documentation. -It complements, but should not duplicate, the following resources: - -* The AsciiDoc, RedHat, and project-specific foreman-documentation style packages for the Vale linter. -See [Vale for writers at Red Hat](https://redhat-documentation.github.io/vale-at-red-hat/docs/main/user-guide/introduction/). -* [Red Hat supplementary style guide for product documentation](https://redhat-documentation.github.io/supplementary-style-guide/) - -### Code conventions - -Use the following markup conventions: - -* Use UTF-8 character encoding in source files. -* Do not add trailing whitespace on lines and in files. -Some editors can help with this. -For example, VS Code has multiple settings related to handling whitespaces. -Whitespace after partial files has to be handled in the file using the `include::` directive. -* Surround user input with underscores (`_`) to indicate variable input, for example, `hammer organization create --name "_My_Organization_"`. - -### Images - -Each guide directory contains an `images/` subdirectory with `images/common` symlink into the `common/images/` directory. - -* Save images local to the guide to the `images/` directory. -* Save images which are supposed to be reused across guides to the `images/common/` directory. - -You can create upstream diagrams using [diagrams.net](https://www.diagrams.net/). -Place the editable diagram in `drawio` format in `guides/image-sources/`. -For inclusion in the content, export diagrams to SVG and place them as described above. - -### AsciiDoc attributes for different build targets - -Because the content in this repository is shared between the upstream Foreman community and branded downstream products, many terms need to be written using AsciiDoc attributes. -For example, never write "Foreman", "Satellite", or "orcharhino" words directly, but use the `{Project}` attribute. - -The attributes used in this repository are defined in the following files: - -* [attributes.adoc](common/attributes.adoc): version definitions and includes for other attribute files. -* [attributes-base.adoc](common/attributes-base.adoc): base attributes common for all builds. -* [attributes-foreman-el.adoc](common/attributes-foreman-el.adoc): base overrides for foreman-el build. -* [attributes-foreman-deb.adoc](common/attributes-foreman-deb.adoc): base overrides for foreman-deb build. -* [attributes-katello.adoc](common/attributes-katello.adoc): base overrides for katello build. -* [attributes-satellite.adoc](common/attributes-satellite.adoc): base overrides for satellite build. -* [attributes-orcharhino.adoc](common/attributes-orcharhino.adoc): base overrides for orcharhino build. - -By default, attributes cannot be used in shell or code examples. -To use them, use the "attributes" keyword: - - [options="nowrap" subs="+quotes,attributes"] - ---- - # ls {AttributeName} - ---- - -### Conditional content - -If a piece of your content, such as a block, paragraph, warning, or chapter, is specific for a certain build target, use AsciiDoc conditionals to show or hide it. - -To show a piece of content only for the `katello` build: - - ifdef::katello[] - NOTE: This part is only relevant for Foreman with the Katello plugin. - endif::[] - -To hide a piece of content for `katello` but show it for all other builds: - - ifndef::katello[] - NOTE: This part is relevant for Foreman without the Katello plugin, but also Satellite and orcharhino. - endif::[] - -Use comma for logic "or": - - ifdef::katello,satellite[] - NOTE: This part is only relevant for deployments with Katello plugin or in Satellite environment. - endif::[] - -Some files are included in different contexts, there are attributes to find the correct context. -In these cases use both `ifdef` and `ifeval`: - - ifdef::foreman-el,foreman-deb[] - ifeval::["{context}" == "{project-context}"] - * A minimum of 4 GB RAM is required for {ProjectServer} to function. - endif::[] - endif::[] - -### File structure - -If you create a new file, use the file structure described here. - -Documentation in this directory follows a modular structure described in the [Modular documentation reference guide](https://redhat-documentation.github.io/modular-docs/). -To write new documentation, you can use [modular documentation templates](https://github.com/redhat-documentation/modular-docs/tree/main/modular-docs-manual/files) or copy an existing file from `guides/common/modules/` and adapt it. - -Included files are kept in the `common/` subdirectory and have prefixes to distinguish their type of content. - -Assemblies are kept at the top of the `common/` subdirectory: - -* [`assembly`](https://redhat-documentation.github.io/modular-docs/#forming-assemblies): Files starting with `assembly_` contain user stories and the modules required to accomplish those user stories. -See the [assembly template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_ASSEMBLY_a-collection-of-modules.adoc). -* In this repository, do not nest assemblies. This means that assemblies cannot contain includes of other assemblies. This guidance overrides the Modular documentation recommendations. -* Do not include assemblies without leveloffset or with leveloffset of two or more in `master.adoc` files. - -Modules are kept in the `common/modules/` subdirectory: - -* [`con`](https://redhat-documentation.github.io/modular-docs/#creating-concept-modules): Files starting with `con_` contain concepts and explain the _what_ and _why_. -Their first line contains the `:_mod-docs-content-type: CONCEPT` attribute. -See the [concept template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_CONCEPT_concept-explanation.adoc). -* [`proc`](https://redhat-documentation.github.io/modular-docs/#creating-procedure-modules): Files starting with `proc_` contain procedures and explain _how_ to achieve a specific goal. -Their first line contains the `:_mod-docs-content-type: PROCEDURE` attribute. -See the [procedure template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_PROCEDURE_doing-one-procedure.adoc). -* [`ref`](https://redhat-documentation.github.io/modular-docs/#creating-reference-modules): Files starting with `ref_` contain references and append other files, for example tables with options. -Their first line contains the `:_mod-docs-content-type: REFERENCE` attribute. -See the [reference template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_REFERENCE_reference-material.adoc). -* [`snip`](https://redhat-documentation.github.io/modular-docs/#using_text_snippets_or_text_fragments_writing-mod-docs): Files starting with `snip_` contain snippets that are reused throughout multiple guides, for example admonitions. -Snippets must not contain an ID. - -### Foreman user personas - -In documentation, a user persona is the target user who will be reading the documentation. -Understanding and identifying the target persona of a piece of content helps ensure that the documentation will properly address the user's needs and capabilities. - -Foreman users include people with varying responsibilities and permissions. -Especially in larger organizations, different tasks are performed by different teams. -Therefore, when contributing to Foreman documentation, it can be useful to be aware of and distinguish Foreman user personas. - -#### *User* persona - -* Has limited permissions -* Runs regular Foreman operations -* Example responsibilities: managing content, provisioning hosts, and managing hosts - -#### *Admin* persona - -* Has unlimited permissions, including root access to the Foreman Server -* Example responsibilities: managing Foreman server - -#### *Architect* persona - -* Has no permissions, does not perform practical administrative or management tasks -* Example responsibilities: determining whether Foreman/Katello meets the needs of their organization and planning the deployment - -### Further Information - -* [Contributing Guidelines for Github documentation](https://github.com/github/docs/blob/main/CONTRIBUTING.md) -* [theforeman.org/contribute](https://theforeman.org/contribute.html) -* [7 Git tips for technical writers](https://opensource.com/article/22/11/git-tips-technical-writers) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 120000 index 00000000000..9487b758940 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1 @@ +.cursor/skills/validate-contribution/SKILL.md \ No newline at end of file From 63a4414d8017859a29045221492da86ed2dc94c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 8 May 2026 11:36:38 +0200 Subject: [PATCH 02/19] Add Contributors' Guide with markdown-based build system Create a standalone guide at guides/doc-Contributing/ that consolidates all contribution resources into a single HTML page. Content included: - CONTRIBUTING.md (contribution guidelines) - All documentation skills from .cursor/skills/ (abstract, heading, prerequisites, refactor-adoc, split-web-ui-cli, validate-contribution) - Project-specific Vale rules from .vale/styles/foreman-documentation/ (AvoidBrandedTerminology, Capitalization, OneSentencePerLine) Build system: - Uses kramdown (Ruby markdown processor) instead of asciidoctor - Single build (no BUILD context variants like foreman-el, katello, etc.) - Auto-rebuilds on GitHub when source files change via Makefile dependencies - Output: guides/build/Contributing/index.html Files added: - guides/doc-Contributing/build.rb - Concatenates markdown sources, strips YAML frontmatter, converts to HTML - guides/doc-Contributing/template.html - HTML5 template with responsive CSS, TOC sidebar, syntax highlighting - guides/doc-Contributing/Makefile - Build system with dependency tracking - guides/doc-Contributing/README.md - Documentation for using the guide Modified: - Gemfile - Added kramdown and kramdown-parser-gfm gems - guides/Makefile - Excluded doc-Contributing from BUILD matrix, added separate 'contributing' target The guide auto-rebuilds in GitHub Actions when CONTRIBUTING.md, skill files, or Vale rules are modified. No workflow changes needed. Co-Authored-By: Claude Sonnet 4.5 --- Gemfile | 4 + guides/Makefile | 16 +- guides/doc-Contributing/Makefile | 26 +++ guides/doc-Contributing/README.md | 156 +++++++++++++ guides/doc-Contributing/build.rb | 210 +++++++++++++++++ guides/doc-Contributing/template.html | 311 ++++++++++++++++++++++++++ 6 files changed, 720 insertions(+), 3 deletions(-) create mode 100644 guides/doc-Contributing/Makefile create mode 100644 guides/doc-Contributing/README.md create mode 100644 guides/doc-Contributing/build.rb create mode 100644 guides/doc-Contributing/template.html diff --git a/Gemfile b/Gemfile index 039f9d01c19..0e1ace3f0cb 100644 --- a/Gemfile +++ b/Gemfile @@ -6,3 +6,7 @@ gem 'sass' # For TOC generation gem 'nokogiri' + +# For Contributors' Guide (markdown to HTML) +gem 'kramdown' +gem 'kramdown-parser-gfm' diff --git a/guides/Makefile b/guides/Makefile index eeca1098300..e57eca84c72 100644 --- a/guides/Makefile +++ b/guides/Makefile @@ -1,14 +1,21 @@ SHELL := /bin/bash -SUBDIRS = $(shell ls -d doc-*) +# All doc- directories except doc-Contributing (which has separate build system) +SUBDIRS = $(shell ls -d doc-* | grep -v 'doc-Contributing') +CONTRIBUTING_DIR = doc-Contributing -.PHONY: all clean html linkchecker linkchecker-tryer serve subdirs $(SUBDIRS) +.PHONY: all clean html linkchecker linkchecker-tryer serve subdirs $(SUBDIRS) contributing all: html -html: subdirs +html: subdirs contributing subdirs: $(SUBDIRS) +contributing: + @if [ -d "$(CONTRIBUTING_DIR)" ]; then \ + $(MAKE) -C "$(CONTRIBUTING_DIR)" html; \ + fi + $(SUBDIRS): $(MAKE) -C "$@" $(MAKECMDGOALS) @@ -16,6 +23,9 @@ clean: @for DIR in $(SUBDIRS) ; do \ $(MAKE) -s --directory="$$DIR" clean ; \ done + @if [ -d "$(CONTRIBUTING_DIR)" ]; then \ + $(MAKE) -s --directory="$(CONTRIBUTING_DIR)" clean ; \ + fi linkchecker: find build -type f -name index\*html | xargs linkchecker -r1 -f common/linkchecker.ini --check-extern diff --git a/guides/doc-Contributing/Makefile b/guides/doc-Contributing/Makefile new file mode 100644 index 00000000000..d699240417a --- /dev/null +++ b/guides/doc-Contributing/Makefile @@ -0,0 +1,26 @@ +SHELL := /bin/bash +BUILD_DIR = ../build/Contributing +OUTPUT = $(BUILD_DIR)/index.html + +# Find all skill files and vale rules dynamically +SKILL_FILES = $(shell find ../../.cursor/skills -name 'SKILL.md' 2>/dev/null) +VALE_RULES = $(shell find ../../.vale/styles/foreman-documentation -name '*.yml' 2>/dev/null) +SOURCES = build.rb template.html ../../CONTRIBUTING.md $(SKILL_FILES) $(VALE_RULES) + +.PHONY: all html clean serve + +all: html + +html: $(OUTPUT) + +$(OUTPUT): $(SOURCES) + @mkdir -p $(BUILD_DIR) + bundle exec ruby build.rb + +clean: + @rm -rf $(BUILD_DIR) + +serve: html + @echo "Serving Contributors' Guide at http://localhost:8813" + @echo "Press Ctrl+C to stop" + python3 -m http.server --directory $(BUILD_DIR) 8813 diff --git a/guides/doc-Contributing/README.md b/guides/doc-Contributing/README.md new file mode 100644 index 00000000000..c540a54d244 --- /dev/null +++ b/guides/doc-Contributing/README.md @@ -0,0 +1,156 @@ +# Contributors' Guide + +This directory contains a standalone guide for documentation contributors that consolidates all contribution resources into a single HTML page. + +## What's Included + +The guide automatically combines: + +- **CONTRIBUTING.md** - Introduction to contribution guidelines +- **Documentation Skills** - All slash commands in `.cursor/skills/*/SKILL.md` +- **Vale Rules** - Project-specific linting rules in `.vale/styles/foreman-documentation/` + +## Building Locally + +### Build the guide: + +```bash +cd guides/doc-Contributing +make html +``` + +Output: `guides/build/Contributing/index.html` + +**Note:** `make html` only rebuilds if source files have changed. If you want to force a fresh build, clean build artifacts first: + +```bash +make clean && make html +``` + +Otherwise, you'll get an error "Nothing to be done for 'html'" + +### View the guide: + +```bash +make serve +# Opens at http://localhost:8813 +``` + +## Auto-Rebuild + +The guide **automatically rebuilds** when source files change: + +### On GitHub (CI/CD) + +When you push changes to: +- `CONTRIBUTING.md` +- Any skill file (`.cursor/skills/*/SKILL.md`) +- Any Vale rule (`.vale/styles/foreman-documentation/*.yml`) + +GitHub Actions will: +1. Detect the change via Makefile dependencies +2. Rebuild the guide automatically +3. Include it in PR previews + +No manual intervention needed! + +### Locally + +The Makefile tracks dependencies automatically. Running `make html` will: +- Check if source files changed since last build +- Rebuild only if needed +- Skip if already up-to-date + +## File Structure + +``` +guides/doc-Contributing/ +├── README.md # This file +├── Makefile # Build system with dependency tracking +├── build.rb # Ruby script: concatenate markdown → HTML +├── template.html # HTML5 template with CSS and TOC +└── build/ # Generated output (gitignored) + └── index.html # Final HTML guide +``` + +## How It Works + +1. **build.rb** reads and concatenates: + - CONTRIBUTING.md content + - All skill files (strips YAML frontmatter) + - Vale rules (formatted as YAML code blocks) + +2. **kramdown** converts the combined markdown to HTML + +3. **template.html** wraps the HTML with: + - Responsive CSS styling + - Table of contents sidebar + - Syntax highlighting + +4. Output written to `guides/build/Contributing/index.html` + +## Integration with Main Build + +The contributors' guide is built alongside other guides: + +```bash +# From repository root +make html # Builds all guides + contributors' guide +make build-foreman-el # Builds foreman-el guides + contributors' guide +``` + +The `guides/Makefile` excludes `doc-Contributing` from the BUILD matrix and builds it separately via the `contributing` target. + +## Troubleshooting + +### Make says "Nothing to be done for 'html'" + +This is normal! Make only rebuilds when source files have changed since the last build. + +**To force a rebuild:** +```bash +make clean && make html +``` + +**To verify auto-rebuild works:** +1. Modify a source file: `touch ../../CONTRIBUTING.md` +2. Run `make html` - should rebuild +3. Run `make html` again - should say "Nothing to be done" (correct!) + +### Build fails with "kramdown not found" + +Run `bundle install` from the repository root to install dependencies. + +### Output file not updating after source changes + +Check that source files are actually newer than the output: +```bash +stat -c '%Y' ../../CONTRIBUTING.md ../build/Contributing/index.html +``` + +The source timestamp should be larger (newer) than the output timestamp. + +### Serve port already in use + +The default port is 8813. Change it: +```bash +python3 -m http.server --directory ../build/Contributing 9000 +``` + +## Adding New Content + +### Add a new skill: + +1. Create `.cursor/skills/new-skill/SKILL.md` +2. Run `make html` - automatically detected and included + +### Add a new Vale rule: + +1. Create `.vale/styles/foreman-documentation/NewRule.yml` +2. Run `make html` - automatically detected and included + +## Questions? + +- For build system questions: See `guides/common/Makefile` for AsciiDoc guide patterns +- For markdown syntax: See [kramdown documentation](https://kramdown.gettalong.org/) +- For contribution questions: Read the generated guide at `guides/build/Contributing/index.html` diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb new file mode 100644 index 00000000000..ef4dd09e273 --- /dev/null +++ b/guides/doc-Contributing/build.rb @@ -0,0 +1,210 @@ +#!/usr/bin/env ruby +# Build script for Contributors' Guide +# Concatenates markdown sources and converts to HTML + +require 'kramdown' +require 'fileutils' + +# Paths +ROOT_DIR = File.expand_path('../..', __dir__) +GUIDES_BUILD_DIR = File.join(File.dirname(__dir__), 'build') +OUTPUT_DIR = File.join(GUIDES_BUILD_DIR, 'Contributing') +OUTPUT_FILE = File.join(OUTPUT_DIR, 'index.html') +TEMPLATE_FILE = File.join(__dir__, 'template.html') + +# Source files +CONTRIBUTING_MD = File.join(ROOT_DIR, 'CONTRIBUTING.md') +SKILLS_DIR = File.join(ROOT_DIR, '.cursor', 'skills') +VALE_RULES_DIR = File.join(ROOT_DIR, '.vale', 'styles', 'foreman-documentation') + +def strip_frontmatter(content) + # Remove YAML frontmatter between --- delimiters + content.sub(/\A---\s*\n.*?\n---\s*\n/m, '') +end + +def read_skill_files + skills = [] + return skills unless Dir.exist?(SKILLS_DIR) + + Dir.glob(File.join(SKILLS_DIR, '*', 'SKILL.md')).sort.each do |skill_file| + skill_name = File.basename(File.dirname(skill_file)) + content = File.read(skill_file) + content = strip_frontmatter(content) + + skills << { + name: skill_name, + content: content + } + end + + skills +end + +def read_vale_rules + rules = [] + return rules unless Dir.exist?(VALE_RULES_DIR) + + Dir.glob(File.join(VALE_RULES_DIR, '*.yml')).sort.each do |rule_file| + rule_name = File.basename(rule_file, '.yml') + content = File.read(rule_file) + + rules << { + name: rule_name, + content: content + } + end + + rules +end + +def build_markdown + markdown = [] + + # Add title + markdown << "# Contributors' Guide" + markdown << "" + markdown << "*This guide consolidates all contribution resources for the Foreman Documentation project.*" + markdown << "" + markdown << "Last updated: #{Time.now.strftime('%Y-%m-%d')}" + markdown << "" + markdown << "---" + markdown << "" + + # Add CONTRIBUTING.md + if File.exist?(CONTRIBUTING_MD) + markdown << File.read(CONTRIBUTING_MD) + markdown << "" + markdown << "---" + markdown << "" + end + + # Add skills section + skills = read_skill_files + unless skills.empty? + markdown << "# Documentation Skills" + markdown << "" + markdown << "The repository includes specialized skills (slash commands) for common documentation tasks." + markdown << "These can be invoked in AI-assisted editors like Claude Code or Cursor." + markdown << "" + + skills.each do |skill| + markdown << "## Skill: #{skill[:name]}" + markdown << "" + markdown << skill[:content] + markdown << "" + end + + markdown << "---" + markdown << "" + end + + # Add Vale rules section + rules = read_vale_rules + unless rules.empty? + markdown << "# Project-Specific Vale Rules" + markdown << "" + markdown << "The following custom Vale rules enforce documentation standards specific to Foreman." + markdown << "These rules are located in `.vale/styles/foreman-documentation/`." + markdown << "" + + rules.each do |rule| + markdown << "## Rule: #{rule[:name]}" + markdown << "" + markdown << "**File:** `.vale/styles/foreman-documentation/#{rule[:name]}.yml`" + markdown << "" + markdown << "```yaml" + markdown << rule[:content] + markdown << "```" + markdown << "" + end + end + + markdown.join("\n") +end + +def convert_to_html(markdown_content) + # Convert markdown to HTML using kramdown + doc = Kramdown::Document.new( + markdown_content, + input: 'GFM', + syntax_highlighter: 'rouge', + syntax_highlighter_opts: { + line_numbers: false, + css_class: 'highlight' + }, + auto_ids: true, + toc_levels: (1..3).to_a + ) + + doc.to_html +end + +def generate_toc(markdown_content) + # Extract headings for TOC + toc = [] + markdown_content.each_line do |line| + # Match markdown headings (# through ###) + if line =~ /^(\#{1,3})\s+(.+)$/ + level = $1.length + title = $2.strip + # Create anchor from title + anchor = title.downcase.gsub(/[^\w\s-]/, '').gsub(/\s+/, '-') + toc << { level: level, title: title, anchor: anchor } + end + end + toc +end + +def inject_into_template(html_content, markdown_content) + unless File.exist?(TEMPLATE_FILE) + puts "Warning: Template file not found at #{TEMPLATE_FILE}" + puts "Creating basic HTML output without template." + return "#{html_content}" + end + + template = File.read(TEMPLATE_FILE) + toc = generate_toc(markdown_content) + + # Build TOC HTML + toc_html = toc.map do |item| + indent = ' ' * (item[:level] - 1) + "#{indent}
  • #{item[:title]}
  • " + end.join("\n") + + # Replace placeholders in template + template.gsub!('{{CONTENT}}', html_content) + template.gsub!('{{TOC}}', toc_html) + template.gsub!('{{BUILD_DATE}}', Time.now.strftime('%Y-%m-%d %H:%M:%S')) + + template +end + +# Main build process +def build + puts "Building Contributors' Guide..." + + # Create output directory + FileUtils.mkdir_p(OUTPUT_DIR) + + # Build markdown content + puts " - Concatenating markdown sources..." + markdown_content = build_markdown + + # Convert to HTML + puts " - Converting to HTML..." + html_content = convert_to_html(markdown_content) + + # Inject into template + puts " - Applying template..." + final_html = inject_into_template(html_content, markdown_content) + + # Write output + puts " - Writing to #{OUTPUT_FILE}..." + File.write(OUTPUT_FILE, final_html) + + puts "Build complete! Output: #{OUTPUT_FILE}" + puts " Size: #{File.size(OUTPUT_FILE)} bytes" +end + +# Run build +build diff --git a/guides/doc-Contributing/template.html b/guides/doc-Contributing/template.html new file mode 100644 index 00000000000..fc40c83247f --- /dev/null +++ b/guides/doc-Contributing/template.html @@ -0,0 +1,311 @@ + + + + + + Contributors' Guide - Foreman Documentation + + + +
    + + +
    + {{CONTENT}} + + +
    +
    + + From a6ce2487a19742c1bd7e65b52ed274565e9cf174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 8 May 2026 12:06:12 +0200 Subject: [PATCH 03/19] Re-create a manual CONTRIBUTING.md --- .cursor/skills/validate-contribution/SKILL.md | 58 ---------------- CONTRIBUTING.md | 68 ++++++++++++++++++- 2 files changed, 67 insertions(+), 59 deletions(-) mode change 120000 => 100644 CONTRIBUTING.md diff --git a/.cursor/skills/validate-contribution/SKILL.md b/.cursor/skills/validate-contribution/SKILL.md index 3e01dd7d58b..891b05abe5f 100644 --- a/.cursor/skills/validate-contribution/SKILL.md +++ b/.cursor/skills/validate-contribution/SKILL.md @@ -3,64 +3,6 @@ name: validate-contribution description: Validate and auto-fix documentation contributions against project guidelines disable-model-invocation: false --- -# Contributing to Foreman Documentation - -If you need help to get started, open an issue, ask the docs team on [Matrix](https://matrix.to/#/#theforeman-doc:matrix.org), or ping [`@docs`](https://community.theforeman.org/g/docs) on the [Foreman Community Forum](https://community.theforeman.org/). - -## Contributor's pledge - -As a contributor, I will: - -* Familiarize myself with the [Pull Request Checklist](#Pull-Request-Checklist) and [Foreman documentation conventions guide](#Foreman-documentation-conventions-guide). -* Open additional issues if my contribution is incomplete. -* Put in my best effort to ensure that my contribution does not worsen the state of any build target. -For example, this might include reviewing how my changes affect upstream build targets even when working on behalf of a downstream product. - -## Maintainer's pledge - -As a maintainer, I will: - -* Help less experienced community members with git, Github, PRs, asciidoc, and asciidoctor and make friendly and helpful comments. -* Only merge PRs if the Github Actions are green. -* Try to review PRs in a timely manner. -* Keep non-trivial PRs open for at least 24 hours (72 hours if over the weekend) to allow for input from the community. -Examples of trivial PRs: Fixing a typo, fixing markup, or fixing links. -Non-trivial PRs might not only benefit from additional review but they also represent an opportunity for community members to ask questions and learn. - -## Pull request checklists - -Checklist for documentation contributions: - -* [ ] My contribution is my own work and I agree to the license of the project. -See [LICENSE](LICENSE). -* [ ] My commits include meaningful commit messages. -See [seven rules for git commit messages](https://cbea.ms/git-commit/#seven-rules). -* [ ] My change does not add trailing whitespaces. -Some editors can help with this. -For example, VS Code has multiple settings related to handling whitespaces. - -Checklist for raising PRs: - -* [ ] I re-read my work carefully before raising a PR or before marking a draft PR as ready for review. -This can include using `git show`, viewing the diff against master or the target branch, running a local Vale check, and other methods. -* [ ] My PR description includes a meaningful description of the changes for the community. -* [ ] I fill out the cherry-picking list in the PR description to the best of my abilities to signify which versions my update applies to. -If unsure, I let reviewers know so that they can assist. -* [ ] Before pinging others about my PR, I await the GitHub Actions checks to see if my branch builds. -If a GitHub check fails and I'm unsure how to proceed, I let reviewers know so that they can assist. - -Each PR should undergo tech review. -(Tech review is performed by an Engineer who did not author the PR. It can be skipped if the PR does not significantly change description of product behavior.) - -* [ ] The PR documents a recommended, user-friendly path. -* [ ] The PR removes steps that have been made unnecessary or obsolete. -* [ ] Any steps introduced or updated in the PR have been tested to confirm that they lead to the documented end result. - -Each PR should undergo style review. -(Style review is performed by a Technical Writer who did not author the PR.) - -* [ ] The PR conforms with the team's style guidelines. -* [ ] The PR introduces documentation that describes a user story rather than a product feature. ## Foreman documentation conventions guide diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 120000 index 9487b758940..00000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1 +0,0 @@ -.cursor/skills/validate-contribution/SKILL.md \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000000..bde4dae6035 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,67 @@ +# Contributing to Foreman Documentation + +If you need help to get started, open an issue, ask the docs team on [Matrix](https://matrix.to/#/#theforeman-doc:matrix.org), or ping [`@docs`](https://community.theforeman.org/g/docs) on the [Foreman Community Forum](https://community.theforeman.org/). + +## Contributor's pledge + +As a contributor, I will: + +* Familiarize myself with the [Pull Request Checklist](#Pull-Request-Checklist) and [Foreman documentation conventions guide](#Foreman-documentation-conventions-guide). +* Open additional issues if my contribution is incomplete. +* Put in my best effort to ensure that my contribution does not worsen the state of any build target. +For example, this might include reviewing how my changes affect upstream build targets even when working on behalf of a downstream product. + +## Maintainer's pledge + +As a maintainer, I will: + +* Help less experienced community members with git, Github, PRs, asciidoc, and asciidoctor and make friendly and helpful comments. +* Only merge PRs if the Github Actions are green. +* Try to review PRs in a timely manner. +* Keep non-trivial PRs open for at least 24 hours (72 hours if over the weekend) to allow for input from the community. +Examples of trivial PRs: Fixing a typo, fixing markup, or fixing links. +Non-trivial PRs might not only benefit from additional review but they also represent an opportunity for community members to ask questions and learn. + +## Pull request checklists + +Checklist for documentation contributions: + +* [ ] My contribution is my own work and I agree to the license of the project. +See [LICENSE](LICENSE). +* [ ] My commits include meaningful commit messages. +See [seven rules for git commit messages](https://cbea.ms/git-commit/#seven-rules). +* [ ] My change does not add trailing whitespaces. +Some editors can help with this. +For example, VS Code has multiple settings related to handling whitespaces. + +Checklist for raising PRs: + +* [ ] I re-read my work carefully before raising a PR or before marking a draft PR as ready for review. +This can include using `git show`, viewing the diff against master or the target branch, running a local Vale check, and other methods. +* [ ] My PR description includes a meaningful description of the changes for the community. +* [ ] I fill out the cherry-picking list in the PR description to the best of my abilities to signify which versions my update applies to. +If unsure, I let reviewers know so that they can assist. +* [ ] Before pinging others about my PR, I await the GitHub Actions checks to see if my branch builds. +If a GitHub check fails and I'm unsure how to proceed, I let reviewers know so that they can assist. + +Each PR should undergo tech review. +(Tech review is performed by an Engineer who did not author the PR. It can be skipped if the PR does not significantly change description of product behavior.) + +* [ ] The PR documents a recommended, user-friendly path. +* [ ] The PR removes steps that have been made unnecessary or obsolete. +* [ ] Any steps introduced or updated in the PR have been tested to confirm that they lead to the documented end result. + +Each PR should undergo style review. +(Style review is performed by a Technical Writer who did not author the PR.) + +* [ ] The PR conforms with the team's style guidelines. +* [ ] The PR introduces documentation that describes a user story rather than a product feature. + +## Foreman documentation conventions guide + +The `Foreman documentation conventions guide` describes guidelines specific to working on Foreman documentation. +It complements, but should not duplicate, the following resources: + +* The AsciiDoc, RedHat, and project-specific foreman-documentation style packages for the Vale linter. +See [Vale for writers at Red Hat](https://redhat-documentation.github.io/vale-at-red-hat/docs/main/user-guide/introduction/). +* [Red Hat supplementary style guide for product documentation](https://redhat-documentation.github.io/supplementary-style-guide/) From bc604e732a6ee93cbac370dc6a7cc36561aa8b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 12:23:48 +0200 Subject: [PATCH 04/19] Apply suggestion from @maximiliankolb Co-authored-by: Maximilian Kolb --- .cursor/skills/validate-contribution/SKILL.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.cursor/skills/validate-contribution/SKILL.md b/.cursor/skills/validate-contribution/SKILL.md index 891b05abe5f..42ae9f37e62 100644 --- a/.cursor/skills/validate-contribution/SKILL.md +++ b/.cursor/skills/validate-contribution/SKILL.md @@ -102,6 +102,8 @@ Assemblies are kept at the top of the `common/` subdirectory: * [`assembly`](https://redhat-documentation.github.io/modular-docs/#forming-assemblies): Files starting with `assembly_` contain user stories and the modules required to accomplish those user stories. See the [assembly template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_ASSEMBLY_a-collection-of-modules.adoc). +* In this repository, do not nest assemblies. This means that assemblies cannot contain includes of other assemblies. This guidance overrides the Modular documentation recommendations. +* Do not include assemblies without leveloffset or with leveloffset of two or more in `master.adoc` files. Modules are kept in the `common/modules/` subdirectory: From 3f5e82fe742732af3eb0336137dd05c4fdf8fee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 12:42:02 +0200 Subject: [PATCH 05/19] Fix up minor duplication --- .cursor/skills/validate-contribution/SKILL.md | 7 ------- CONTRIBUTING.md | 7 ++----- guides/doc-Contributing/build.rb | 6 +++++- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/.cursor/skills/validate-contribution/SKILL.md b/.cursor/skills/validate-contribution/SKILL.md index 42ae9f37e62..d82756e4376 100644 --- a/.cursor/skills/validate-contribution/SKILL.md +++ b/.cursor/skills/validate-contribution/SKILL.md @@ -6,13 +6,6 @@ disable-model-invocation: false ## Foreman documentation conventions guide -The `Foreman documentation conventions guide` describes guidelines specific to working on Foreman documentation. -It complements, but should not duplicate, the following resources: - -* The AsciiDoc, RedHat, and project-specific foreman-documentation style packages for the Vale linter. -See [Vale for writers at Red Hat](https://redhat-documentation.github.io/vale-at-red-hat/docs/main/user-guide/introduction/). -* [Red Hat supplementary style guide for product documentation](https://redhat-documentation.github.io/supplementary-style-guide/) - ### Code conventions Use the following markup conventions: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bde4dae6035..453acfc18d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,11 +57,8 @@ Each PR should undergo style review. * [ ] The PR conforms with the team's style guidelines. * [ ] The PR introduces documentation that describes a user story rather than a product feature. -## Foreman documentation conventions guide +## Additional resources -The `Foreman documentation conventions guide` describes guidelines specific to working on Foreman documentation. -It complements, but should not duplicate, the following resources: - -* The AsciiDoc, RedHat, and project-specific foreman-documentation style packages for the Vale linter. +* The AsciiDoc and RedHat style packages for the Vale linter. See [Vale for writers at Red Hat](https://redhat-documentation.github.io/vale-at-red-hat/docs/main/user-guide/introduction/). * [Red Hat supplementary style guide for product documentation](https://redhat-documentation.github.io/supplementary-style-guide/) diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index ef4dd09e273..bd29b114145 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -63,7 +63,11 @@ def build_markdown # Add title markdown << "# Contributors' Guide" markdown << "" - markdown << "*This guide consolidates all contribution resources for the Foreman Documentation project.*" + markdown << "This guide consolidates contribution resources for the Foreman Documentation project." + markdown << "It concatenates resources from the following sources:" + markdown << " - [CONTRIBUTING.md](../../CONTRIBUTING.md)" + markdown << " - [Documentation Skills](../../.claude/skills)" + markdown << " - [Vale Rules for Foreman documentation](../../.vale/styles/foreman-documentation)" markdown << "" markdown << "Last updated: #{Time.now.strftime('%Y-%m-%d')}" markdown << "" From d0065a49c3bdd532069569881652b1c29e2150ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 14:50:47 +0200 Subject: [PATCH 06/19] Update for the new locations of skills --- .claude/skills/heading/SKILL.md | 2 +- {.cursor => .claude}/skills/validate-contribution/SKILL.md | 0 guides/doc-Contributing/README.md | 6 +++--- guides/doc-Contributing/build.rb | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename {.cursor => .claude}/skills/validate-contribution/SKILL.md (100%) diff --git a/.claude/skills/heading/SKILL.md b/.claude/skills/heading/SKILL.md index 8463d1eb5fc..c9f75626e08 100644 --- a/.claude/skills/heading/SKILL.md +++ b/.claude/skills/heading/SKILL.md @@ -28,7 +28,7 @@ Additional principles for specific heading types: ## Post-command cleanup -* If you rename a heading, use the `.cursor/skills/refactor-adoc.md` command to update the module's ID, filename, and all references and links to the module in the repository. +* If you rename a heading, use the `.claude/skills/refactor-adoc.md` command to update the module's ID, filename, and all references and links to the module in the repository. ## Examples of good headings diff --git a/.cursor/skills/validate-contribution/SKILL.md b/.claude/skills/validate-contribution/SKILL.md similarity index 100% rename from .cursor/skills/validate-contribution/SKILL.md rename to .claude/skills/validate-contribution/SKILL.md diff --git a/guides/doc-Contributing/README.md b/guides/doc-Contributing/README.md index c540a54d244..1b8d48f31bc 100644 --- a/guides/doc-Contributing/README.md +++ b/guides/doc-Contributing/README.md @@ -7,7 +7,7 @@ This directory contains a standalone guide for documentation contributors that c The guide automatically combines: - **CONTRIBUTING.md** - Introduction to contribution guidelines -- **Documentation Skills** - All slash commands in `.cursor/skills/*/SKILL.md` +- **Documentation Skills** - All slash commands in `.claude/skills/*/SKILL.md` - **Vale Rules** - Project-specific linting rules in `.vale/styles/foreman-documentation/` ## Building Locally @@ -44,7 +44,7 @@ The guide **automatically rebuilds** when source files change: When you push changes to: - `CONTRIBUTING.md` -- Any skill file (`.cursor/skills/*/SKILL.md`) +- Any skill file (`.claude/skills/*/SKILL.md`) - Any Vale rule (`.vale/styles/foreman-documentation/*.yml`) GitHub Actions will: @@ -141,7 +141,7 @@ python3 -m http.server --directory ../build/Contributing 9000 ### Add a new skill: -1. Create `.cursor/skills/new-skill/SKILL.md` +1. Create `.claude/skills/new-skill/SKILL.md` 2. Run `make html` - automatically detected and included ### Add a new Vale rule: diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index bd29b114145..680c19b3fb5 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -14,7 +14,7 @@ # Source files CONTRIBUTING_MD = File.join(ROOT_DIR, 'CONTRIBUTING.md') -SKILLS_DIR = File.join(ROOT_DIR, '.cursor', 'skills') +SKILLS_DIR = File.join(ROOT_DIR, '.claude', 'skills') VALE_RULES_DIR = File.join(ROOT_DIR, '.vale', 'styles', 'foreman-documentation') def strip_frontmatter(content) From 17d9621b8a5c0db627ad3140fcae1c6a16b148c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 15:16:49 +0200 Subject: [PATCH 07/19] Improve guide intro --- guides/doc-Contributing/build.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index 680c19b3fb5..c44e469b7b0 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -61,14 +61,15 @@ def build_markdown markdown = [] # Add title - markdown << "# Contributors' Guide" + markdown << "# About the Foreman Documentation Contributors' Guide" markdown << "" - markdown << "This guide consolidates contribution resources for the Foreman Documentation project." - markdown << "It concatenates resources from the following sources:" + markdown << "The Foreman Documentation Contributors' Guide consolidates contribution resources for the Foreman Documentation project. It consolidates resources from the following sources:" markdown << " - [CONTRIBUTING.md](../../CONTRIBUTING.md)" markdown << " - [Documentation Skills](../../.claude/skills)" markdown << " - [Vale Rules for Foreman documentation](../../.vale/styles/foreman-documentation)" markdown << "" + markdown << "The guide concatenates resources from the above sources into a single guide for easy reference. For more information, see the [README](README.md)." + markdown << "" markdown << "Last updated: #{Time.now.strftime('%Y-%m-%d')}" markdown << "" markdown << "---" From cf76cf1d3e009d7aed85125e003add17e4b0225d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 15:43:30 +0200 Subject: [PATCH 08/19] Update list of skills to pull in skill name from the file --- .claude/skills/abstract/SKILL.md | 10 +++++----- .claude/skills/heading/SKILL.md | 12 ++++++------ .claude/skills/prerequisites/SKILL.md | 12 ++++++------ guides/doc-Contributing/build.rb | 17 ++++++++++++++++- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/.claude/skills/abstract/SKILL.md b/.claude/skills/abstract/SKILL.md index 20ce057e45a..bb4a87f6cc4 100644 --- a/.claude/skills/abstract/SKILL.md +++ b/.claude/skills/abstract/SKILL.md @@ -1,14 +1,14 @@ --- -name: abstract +name: Abstracts description: Review or write an abstract (also called a short description) for a documentation module --- -# Review or write abstract +### Review or write abstract -## Overview +#### Overview Review and improve the abstract for this file. Write it if it doesn't exist yet. -## Definition of an abstract +#### Definition of an abstract An abstract is the first paragraph of the module. It follows after the module heading. @@ -22,7 +22,7 @@ Abstracts typically contain the following information: - The "Why" - Where appropriate, an example use case -## Instructions +#### Instructions When reviewing or writing the abstract, follow these principles: diff --git a/.claude/skills/heading/SKILL.md b/.claude/skills/heading/SKILL.md index c9f75626e08..5491b13b1b0 100644 --- a/.claude/skills/heading/SKILL.md +++ b/.claude/skills/heading/SKILL.md @@ -1,16 +1,16 @@ --- -name: heading +name: Headings description: Review or write heading --- -# Review or write heading +### Review or write heading -## Overview +#### Overview Review and improve the heading for this file. Write it if it doesn't exist yet. -## Instructions +#### Instructions Follow these general principles for all headings: @@ -26,11 +26,11 @@ Additional principles for specific heading types: * For assemblies (the first con_*.adoc in an assembly_*.adoc) that contain at least one procedure: Start the heading with a gerund. * For assemblies (the first con_*.adoc in an assembly_*.adoc) that contain only concepts or references: Do not start the heading with a gerund or verb. Use a noun phrase. -## Post-command cleanup +#### Post-command cleanup * If you rename a heading, use the `.claude/skills/refactor-adoc.md` command to update the module's ID, filename, and all references and links to the module in the repository. -## Examples of good headings +#### Examples of good headings Concept headings: diff --git a/.claude/skills/prerequisites/SKILL.md b/.claude/skills/prerequisites/SKILL.md index 597faa96eec..fb15e65bea4 100644 --- a/.claude/skills/prerequisites/SKILL.md +++ b/.claude/skills/prerequisites/SKILL.md @@ -1,14 +1,14 @@ --- -name: prerequisites +name: Prerequisites description: Review or add prerequisites --- -# Review or add prerequisites +### Review or add prerequisites -## Overview +#### Overview Review prerequisites in this file to make sure they are labeled correctly and use consistent formatting. Prerequisites are a bulleted list of conditions that must be satisfied before the user starts the procedure. -## Instructions +#### Instructions 1. Only process procedure modules (proc_*.adoc). These are the only modules that can include a `.Prerequisites` section. 2. If a section titled `.Prerequisites` exists in the file, ensure it uses consistent formatting: @@ -26,7 +26,7 @@ Review prerequisites in this file to make sure they are labeled correctly and us - Do not exceed 10 prerequisites. If `.Prerequisites` includes more than 10 list items, flag this as an issue for human review. 3. If a procedure module does not include `.Prerequisites` section, scan the module to identify steps that meet criteria for prerequisites. If a step or steps like this exist, create a `.Prerequisites` section and rephrase the step or steps as prerequisites in this section. -## Examples of good prerequisites +#### Examples of good prerequisites * The `kernelcare` package is installed on your hosts. * The base system of the {SmartProxy} is registered to the newly upgraded {ProjectServer}. @@ -34,7 +34,7 @@ Review prerequisites in this file to make sure they are labeled correctly and us * You are logged in to the registry.redhat.io container registry. * If you use `dzdo` for Ansible jobs, the `community.general` Ansible collection must be installed. -## Examples of bad prerequisites +#### Examples of bad prerequisites * You are logged in. (This is an obvious prerequisite.) * The host is registered to {Project}. (This is an obvious prerequisite.) diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index c44e469b7b0..fbfb2a447ab 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -22,13 +22,28 @@ def strip_frontmatter(content) content.sub(/\A---\s*\n.*?\n---\s*\n/m, '') end +def extract_frontmatter_field(content, field) + match = content.match(/\A---\s*\n(.*?)\n---\s*\n/m) + return nil unless match + + match[1].each_line do |line| + stripped = line.strip + prefix = "#{field}:" + next unless stripped.start_with?(prefix) + + return stripped[prefix.length..].strip + end + nil +end + def read_skill_files skills = [] return skills unless Dir.exist?(SKILLS_DIR) Dir.glob(File.join(SKILLS_DIR, '*', 'SKILL.md')).sort.each do |skill_file| - skill_name = File.basename(File.dirname(skill_file)) content = File.read(skill_file) + skill_name = extract_frontmatter_field(content, 'name') || + File.basename(File.dirname(skill_file)) content = strip_frontmatter(content) skills << { From f6f6c68019ebe0e4aeb76517a53f20dc42f7bb43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 16:07:42 +0200 Subject: [PATCH 09/19] Display skills based on categories --- guides/doc-Contributing/README.md | 2 ++ guides/doc-Contributing/build.rb | 43 ++++++++++++++++++++++++++----- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/guides/doc-Contributing/README.md b/guides/doc-Contributing/README.md index 1b8d48f31bc..8e04c632339 100644 --- a/guides/doc-Contributing/README.md +++ b/guides/doc-Contributing/README.md @@ -10,6 +10,8 @@ The guide automatically combines: - **Documentation Skills** - All slash commands in `.claude/skills/*/SKILL.md` - **Vale Rules** - Project-specific linting rules in `.vale/styles/foreman-documentation/` +Skills are automatically organized into categories in the generated guide for easier navigation. + ## Building Locally ### Build the guide: diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index fbfb2a447ab..137b155c2b4 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -36,18 +36,36 @@ def extract_frontmatter_field(content, field) nil end +def categorize_skill(skill_dir_name) + # Map skill directory names to categories + categories = { + 'abstract' => 'Style Guidelines', + 'heading' => 'Style Guidelines', + 'prerequisites' => 'Style Guidelines', + 'review-assembly-user-story' => 'Content Structure', + 'split-web-ui-cli' => 'Content Structure', + 'refactor-adoc' => 'File Management', + 'validate-contribution' => 'Validation and Review' + } + + categories[skill_dir_name] || 'Other' +end + def read_skill_files skills = [] return skills unless Dir.exist?(SKILLS_DIR) + # Look for skills: .claude/skills/skill-name/SKILL.md Dir.glob(File.join(SKILLS_DIR, '*', 'SKILL.md')).sort.each do |skill_file| + skill_dir_name = File.basename(File.dirname(skill_file)) content = File.read(skill_file) - skill_name = extract_frontmatter_field(content, 'name') || - File.basename(File.dirname(skill_file)) + skill_name = extract_frontmatter_field(content, 'name') || skill_dir_name content = strip_frontmatter(content) skills << { name: skill_name, + dir_name: skill_dir_name, + category: categorize_skill(skill_dir_name), content: content } end @@ -107,11 +125,24 @@ def build_markdown markdown << "These can be invoked in AI-assisted editors like Claude Code or Cursor." markdown << "" - skills.each do |skill| - markdown << "## Skill: #{skill[:name]}" - markdown << "" - markdown << skill[:content] + # Group skills by category + skills_by_category = skills.group_by { |skill| skill[:category] } + + # Define category order for consistent presentation + category_order = ['Style Guidelines', 'Content Structure', 'File Management', 'Validation and Review', 'Other'] + + category_order.each do |category| + next unless skills_by_category[category] + + markdown << "## #{category}" markdown << "" + + skills_by_category[category].each do |skill| + markdown << "### #{skill[:name]}" + markdown << "" + markdown << skill[:content] + markdown << "" + end end markdown << "---" From ed4a539d3b71c4aa00cb04795ec8a636470fd496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 16:23:10 +0200 Subject: [PATCH 10/19] Update headings and heading levels of skills --- .claude/skills/refactor-adoc/SKILL.md | 6 ++--- .../review-assembly-user-story/SKILL.md | 26 +++++++++---------- .claude/skills/split-web-ui-cli/SKILL.md | 8 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.claude/skills/refactor-adoc/SKILL.md b/.claude/skills/refactor-adoc/SKILL.md index edcd70f0ad4..ea3a488c485 100644 --- a/.claude/skills/refactor-adoc/SKILL.md +++ b/.claude/skills/refactor-adoc/SKILL.md @@ -3,9 +3,9 @@ name: refactor-adoc description: Refactor adoc file by a given title disable-model-invocation: true --- -# Refactor adoc file by a given title +### Refactor adoc file by a given title -## Overview +#### Overview Change the title (if present), ID (if present), and file name of an assembly, module, or snippet according to a new title. Update the includes and any ID references across all documentation. @@ -16,7 +16,7 @@ Usage: /refactor-adoc @old-file.adoc "New title" ``` -## Instructions +#### Instructions Refactor the following `.adoc` file according to the following title. Follow these principles: diff --git a/.claude/skills/review-assembly-user-story/SKILL.md b/.claude/skills/review-assembly-user-story/SKILL.md index 302d84c713d..9d6d7ea04a6 100644 --- a/.claude/skills/review-assembly-user-story/SKILL.md +++ b/.claude/skills/review-assembly-user-story/SKILL.md @@ -1,10 +1,10 @@ --- -name: review-assembly-user-story +name: An assembly covers a single user story description: Review assembly to ensure it follows the one-user-story principle --- -# Review assembly for single user story +### Review assembly for single user story -## Overview +#### Overview Review an assembly file to ensure it describes a single user story. If the assembly contains multiple user stories, split it into separate assembly files. @@ -15,17 +15,17 @@ Usage: /review-assembly-user-story @assembly_example.adoc ``` -## Reasoning +#### Reasoning An assembly must cover a single user story (what the user wants to accomplish). When an assembly attempts to describe multiple user stories, it often loses its focus, becomes too long, and can be confusing to follow. -## Instructions +#### Instructions Review the assembly file to determine if it follows the one-user-story principle. Each assembly must describe a single user story. -### Step 1: Analyze the assembly +##### Step 1: Analyze the assembly Read the assembly file and: @@ -34,7 +34,7 @@ Read the assembly file and: 3. **Review included modules** - Do they all support the same user story, or do they describe separate independent tasks? 4. **Look for clear boundaries** - Are there sections that could stand alone as separate user stories? -### Step 2: Determine if splitting is needed +##### Step 2: Determine if splitting is needed The assembly needs splitting if: @@ -51,7 +51,7 @@ The assembly is fine if: - Procedures are sequential steps or alternative approaches for the same task - Modules provide context, reference, or examples for one user story -### Step 3: If splitting is needed +##### Step 3: If splitting is needed For each identified user story: @@ -61,7 +61,7 @@ For each identified user story: 4. **Update parent files** - Replace the original assembly include with includes for all new assemblies in the `master.adoc` file 5. **Delete the original assembly** - Once all content is split and includes are updated -### Step 4: Report findings +##### Step 4: Report findings Provide a summary that includes: @@ -69,19 +69,19 @@ Provide a summary that includes: - If splitting occurred, list the new assembly files created and their user stories - Any recommendations for improving the assembly structure -## Principles +#### Principles - **One user story per assembly** - Each assembly should answer "What does the user want to accomplish?" - **User-centric organization** - Think from the user's perspective, not the product's features - **Cohesive modules** - All modules in an assembly should support the same goal -## Examples +#### Examples -### Good examples (single user story): +##### Good examples (single user story): - `assembly_backing-up-server-and-proxy.adoc` - User wants to back up their system - `assembly_configuring-email-notifications.adoc` - User wants to set up email notifications -### Important considerations: +##### Important considerations: - **Inverse operations belong together** - Creating and deleting (e.g., organizations), or enabling and disabling (e.g., external authentication) are part of the same user story, as users may want to revert their actions - **Alternative methods belong together** - Multiple procedures for the same task (web UI, CLI, API) belong in the same assembly - **Sequential workflows belong together** - If steps must be done in order for one goal, they belong in the same assembly diff --git a/.claude/skills/split-web-ui-cli/SKILL.md b/.claude/skills/split-web-ui-cli/SKILL.md index e7be5c5dd2a..7a73cd1dcbf 100644 --- a/.claude/skills/split-web-ui-cli/SKILL.md +++ b/.claude/skills/split-web-ui-cli/SKILL.md @@ -1,15 +1,15 @@ --- -name: split-web-ui-cli +name: Split a module into web UI and CLI modules description: Split a module into web UI and CLI modules disable-model-invocation: true --- -# Split a module into web UI and CLI modules +### Split a module into web UI and CLI modules -## Overview +#### Overview This file includes a web UI procedure (`.Procedure`) and a CLI procedure (`.CLI procedure`). Split it into two files: `proc_*-by-using-web-ui.adoc` and `proc_*-by-using-cli.adoc`. -## Instructions +#### Instructions Follow these principles: From 5d50a58bfa8b079ff665ee3fa36a4172ae04660e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 16:52:56 +0200 Subject: [PATCH 11/19] Drop the high-level skills category --- guides/doc-Contributing/build.rb | 35 +++++++++++++++----------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index 137b155c2b4..2748b4e3b28 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -39,13 +39,13 @@ def extract_frontmatter_field(content, field) def categorize_skill(skill_dir_name) # Map skill directory names to categories categories = { - 'abstract' => 'Style Guidelines', - 'heading' => 'Style Guidelines', - 'prerequisites' => 'Style Guidelines', - 'review-assembly-user-story' => 'Content Structure', - 'split-web-ui-cli' => 'Content Structure', - 'refactor-adoc' => 'File Management', - 'validate-contribution' => 'Validation and Review' + 'abstract' => 'AI skills: Style Guidelines', + 'heading' => 'AI skills: Style Guidelines', + 'prerequisites' => 'AI skills: Style Guidelines', + 'review-assembly-user-story' => 'AI skills: Content Structure', + 'split-web-ui-cli' => 'AI skills: Content Structure', + 'refactor-adoc' => 'AI skills: File Management', + 'validate-contribution' => 'AI skills: Validation and Review' } categories[skill_dir_name] || 'Other' @@ -119,34 +119,31 @@ def build_markdown # Add skills section skills = read_skill_files unless skills.empty? - markdown << "# Documentation Skills" - markdown << "" - markdown << "The repository includes specialized skills (slash commands) for common documentation tasks." - markdown << "These can be invoked in AI-assisted editors like Claude Code or Cursor." - markdown << "" - # Group skills by category skills_by_category = skills.group_by { |skill| skill[:category] } # Define category order for consistent presentation - category_order = ['Style Guidelines', 'Content Structure', 'File Management', 'Validation and Review', 'Other'] + category_order = ['AI skills: Style Guidelines', 'AI skills: Content Structure', 'AI skills: File Management', 'AI skills: Validation and Review', 'Other'] category_order.each do |category| next unless skills_by_category[category] - markdown << "## #{category}" + markdown << "# #{category}" + markdown << "" + markdown << "The repository includes specialized skills (slash commands) for common documentation tasks." + markdown << "These can be invoked in AI-assisted editors like Claude Code or Cursor." markdown << "" skills_by_category[category].each do |skill| - markdown << "### #{skill[:name]}" + markdown << "## #{skill[:name]}" markdown << "" markdown << skill[:content] markdown << "" end - end - markdown << "---" - markdown << "" + markdown << "---" + markdown << "" + end end # Add Vale rules section From 76e49fca096111dbce0831f35a5523838e9bbcb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 17:16:18 +0200 Subject: [PATCH 12/19] Restructure skills and filter content for Contributors' Guide - Reorganize skill files with standardized sections: - Overview: Human-readable guidelines and definitions - Examples: Good/bad examples with explanations - Instructions: AI-specific workflow steps - Update build.rb to extract only Overview and Examples sections for the Contributors' Guide - Change category headings to top-level in the guide - Fix .claude/skills path (was incorrectly .cursor/skills) - Update all skills except validate-contribution with new structure: abstract, heading, prerequisites, refactor-adoc, review-assembly-user-story, split-web-ui-cli This separates human-facing documentation guidelines from AI-specific instructions, making the Contributors' Guide more focused and useful for human contributors. Co-Authored-By: Claude Sonnet 4.5 --- .claude/skills/abstract/SKILL.md | 45 ++++++----- .claude/skills/heading/SKILL.md | 79 +++++++++---------- .claude/skills/prerequisites/SKILL.md | 72 +++++++++-------- .claude/skills/refactor-adoc/SKILL.md | 18 ++++- .../review-assembly-user-story/SKILL.md | 46 ++++++----- .claude/skills/split-web-ui-cli/SKILL.md | 22 +++++- guides/doc-Contributing/build.rb | 65 ++++++++++++++- 7 files changed, 228 insertions(+), 119 deletions(-) diff --git a/.claude/skills/abstract/SKILL.md b/.claude/skills/abstract/SKILL.md index bb4a87f6cc4..a602ffc96fb 100644 --- a/.claude/skills/abstract/SKILL.md +++ b/.claude/skills/abstract/SKILL.md @@ -6,33 +6,32 @@ description: Review or write an abstract (also called a short description) for a #### Overview -Review and improve the abstract for this file. Write it if it doesn't exist yet. - -#### Definition of an abstract +An abstract is the first paragraph of a documentation module that helps readers and AI-powered search tools find the information they need and confirm they are in the right place. -An abstract is the first paragraph of the module. -It follows after the module heading. -It is prefixed by the `[role="_abstract"]` AsciiDoc tag. +An abstract follows after the module heading and is prefixed by the `[role="_abstract"]` AsciiDoc tag. -Abstracts, also called short descriptions, help readers and AI-powered search tools find the information that they need and confirm that they are in the right place. +Abstracts typically contain: +- The "What" - what the content covers +- The "Why" - why it matters or when to use it +- Where appropriate, an example use case -Abstracts typically contain the following information: +**Guidelines:** +- Do not simply repeat the heading of the module; build upon it +- Avoid self-referential language (e.g., "This procedure...", "This module...", "This table...") +- Avoid feature-centric language (e.g., "This feature...") +- Do not use sentence fragments +- When addressing the user, address them as "you" +- Follow these length constraints: 50-300 characters, 1-2 sentences, a single paragraph -- The "What" -- The "Why" -- Where appropriate, an example use case +**Module-type-specific guidelines:** +- `CONCEPT` modules: See [references/concept.md](references/concept.md) +- `PROCEDURE` modules: See [references/procedure.md](references/procedure.md) +- `REFERENCE` modules: See [references/reference.md](references/reference.md) #### Instructions -When reviewing or writing the abstract, follow these principles: - -- Do not simply repeat the heading of the module; build upon it. -- Avoid self-referential language (for example: avoid "This procedure...", "This module...", "This table..."). -- Avoid feature-centric language (for example: avoid "This feature..."). -- Do not use sentence fragments. -- When addressing the user, address them as "you". -- Follow these length constraints: 50-300 characters, 1-2 sentences, a single paragraph. -- For module-type-specific abstract rules, look up the reference file that matches the `:_mod-docs-content-type:` AsciiDoc attribute in the module (open and apply that file in full): - - `CONCEPT` → [references/concept.md](references/concept.md) - - `PROCEDURE` → [references/procedure.md](references/procedure.md) - - `REFERENCE` → [references/reference.md](references/reference.md) +Review and improve the abstract for this file. Write it if it doesn't exist yet. + +When reviewing or writing the abstract, follow the guidelines in the Overview section. + +For module-type-specific abstract rules, look up the reference file that matches the `:_mod-docs-content-type:` AsciiDoc attribute in the module (open and apply that file in full). diff --git a/.claude/skills/heading/SKILL.md b/.claude/skills/heading/SKILL.md index 5491b13b1b0..1ed43b191b8 100644 --- a/.claude/skills/heading/SKILL.md +++ b/.claude/skills/heading/SKILL.md @@ -7,51 +7,48 @@ description: Review or write heading #### Overview -Review and improve the heading for this file. -Write it if it doesn't exist yet. +Headings should be clear, concise, and use familiar keywords that help users understand what the content covers. + +**General principles for all headings:** +- Make the heading 3-11 words long +- Use clear headings with familiar keywords for users +- Ensure the heading summarizes the contents of the part of the documentation it introduces + +**Module-type-specific principles:** +- **Concepts** (con_*.adoc): Do not start with a gerund or verb. Use a noun phrase and include nouns that appear in the body text. +- **Procedures** (proc_*.adoc): Start the heading with a gerund (e.g., "Configuring...", "Creating..."). +- **References** (ref_*.adoc): Do not start with a gerund or verb. Include nouns that appear in the body text. +- **Assemblies** containing procedures: Start the heading with a gerund. +- **Assemblies** containing only concepts or references: Do not start with a gerund or verb. Use a noun phrase. + +#### Examples + +**Concept headings:** +- Provisioning methods in {Project} +- Security considerations in {Project} +- Host groups overview + +**Procedure headings:** +- Deploying SSH keys during provisioning +- Opening required ports +- Configuring pull-based transport for remote execution + +**Reference headings:** +- Job template examples and extensions +- Host parameter hierarchy +- Operating system requirements + +**Assembly headings:** +- Connecting AI applications to the MCP server for {Project} +- Configuring {SmartProxy} and hosts to authenticate with SSH certificates during remote execution +- Content and patch management with {Project} #### Instructions -Follow these general principles for all headings: +Review and improve the heading for this file. Write it if it doesn't exist yet. -* Make the heading 3-11 words long. -* Use clear headings with familiar keywords for users. -* Ensure the heading summarizes the contents of the part of the documentation it introduces. - -Additional principles for specific heading types: - -* For concepts (con_*.adoc): Do not start the heading with a gerund or verb. Use a noun phrase and include nouns or noun phrases that appear in the body text. -* For procedures (proc_*.adoc): Start the heading with a gerund. -* For references (ref_*.adoc): Do not start the heading with a gerund or verb. Include nouns that appear in the body text. -* For assemblies (the first con_*.adoc in an assembly_*.adoc) that contain at least one procedure: Start the heading with a gerund. -* For assemblies (the first con_*.adoc in an assembly_*.adoc) that contain only concepts or references: Do not start the heading with a gerund or verb. Use a noun phrase. +Follow the principles outlined in the Overview section above. #### Post-command cleanup -* If you rename a heading, use the `.claude/skills/refactor-adoc.md` command to update the module's ID, filename, and all references and links to the module in the repository. - -#### Examples of good headings - -Concept headings: - -* Provisioning methods in {Project} -* Security considerations in {Project} -* Host groups overview - -Procedure headings: - -* Deploying SSH keys during provisioning -* Opening required ports -* Configuring pull-based transport for remote execution - -Reference headings: - -* Job template examples and extensions -* Host parameter hierarchy -* Operating system requirements - -Assembly headings: - -* Connecting AI applications to the MCP server for {Project} -* Configuring {SmartProxy} and hosts to authenticate with SSH certificates during remote execution -* Content and patch management with {Project} +If you rename a heading, use the `/refactor-adoc` command to update the module's ID, filename, and all references and links to the module in the repository. diff --git a/.claude/skills/prerequisites/SKILL.md b/.claude/skills/prerequisites/SKILL.md index fb15e65bea4..83b30a240a8 100644 --- a/.claude/skills/prerequisites/SKILL.md +++ b/.claude/skills/prerequisites/SKILL.md @@ -6,38 +6,48 @@ description: Review or add prerequisites #### Overview -Review prerequisites in this file to make sure they are labeled correctly and use consistent formatting. Prerequisites are a bulleted list of conditions that must be satisfied before the user starts the procedure. +Prerequisites are a bulleted list of conditions that must be satisfied before the user starts a procedure. Only procedure modules (proc_*.adoc) can include a `.Prerequisites` section. + +**What prerequisites are:** +- Checks that are true before the user begins +- Conditions the user must have completed beforehand +- Items the user must have ready +- Actions that the user, another person, or technology has completed before the user can begin + +**Formatting guidelines:** +- The first word of each prerequisite must be capitalized +- Each prerequisite must start with a bullet point +- Prerequisites must not use imperative voice +- If prerequisites are full sentences, end all with a period +- If prerequisites are sentence fragments, do not use any end punctuation +- Use passive voice for prerequisites representing an action not completed by the current user +- Prerequisites must use parallel language (all sentences or all fragments, not mixed) + +**Content guidelines:** +- Focus on relevant prerequisites that users might not otherwise be aware of +- Do not list obvious prerequisites +- Do not include procedure steps in prerequisites +- Do not exceed 10 prerequisites + +#### Examples + +**Good prerequisites:** +- The `kernelcare` package is installed on your hosts. +- The base system of the {SmartProxy} is registered to the newly upgraded {ProjectServer}. +- Your user account has a role that grants the `view_policies` permission. +- You are logged in to the registry.redhat.io container registry. +- If you use `dzdo` for Ansible jobs, the `community.general` Ansible collection must be installed. + +**Bad prerequisites (and why):** +- You are logged in. *(Obvious prerequisite)* +- The host is registered to {Project}. *(Obvious prerequisite)* +- At least one host exists in {Project}. *(Obvious prerequisite)* +- Ensure the `kernelcare` package is installed on your hosts. *(Uses imperative voice)* +- Install the `kernelcare` package on your hosts. *(Phrased like a procedure step)* #### Instructions 1. Only process procedure modules (proc_*.adoc). These are the only modules that can include a `.Prerequisites` section. -2. If a section titled `.Prerequisites` exists in the file, ensure it uses consistent formatting: - - The first word of each prerequisite must be capitalized. - - Each prerequisite must start with a bullet point. - - Prerequisites must not use imperative voice. - - If the prerequisites are full sentences, end all prerequisites with a period. - - If the prerequisites are sentence fragments, do not use any end punctuation. - - Use passive voice for prerequisites that represent an action that is not completed by the current user. For example, having a configuration enabled by a system admin. - - Prerequisites must use parallel language. For example, if one bullet is a complete sentence, write the other bullets as complete sentences. -2. If a section titled `.Prerequisites` exists in the file, ensure it contains information suitable for prerequisites: - - Prerequisites are checks that are true, checks that the user must have completed before they begin a procedure, or items that the user must have ready before beginning a procedure. Prerequisites can also be actions that the user, another person, or piece of technology has completed before the user can begin the procedure. - - Focus on relevant prerequisites that users might not otherwise be aware of. Do not list obvious prerequisites. - - Do not include procedure steps in prerequisites. If `.Prerequisites` includes a prerequisite that would be more suitable as a procedure step, move it to the `.Procedure` section. - - Do not exceed 10 prerequisites. If `.Prerequisites` includes more than 10 list items, flag this as an issue for human review. -3. If a procedure module does not include `.Prerequisites` section, scan the module to identify steps that meet criteria for prerequisites. If a step or steps like this exist, create a `.Prerequisites` section and rephrase the step or steps as prerequisites in this section. - -#### Examples of good prerequisites - -* The `kernelcare` package is installed on your hosts. -* The base system of the {SmartProxy} is registered to the newly upgraded {ProjectServer}. -* Your user account has a role that grants the `view_policies` permission. -* You are logged in to the registry.redhat.io container registry. -* If you use `dzdo` for Ansible jobs, the `community.general` Ansible collection must be installed. - -#### Examples of bad prerequisites - -* You are logged in. (This is an obvious prerequisite.) -* The host is registered to {Project}. (This is an obvious prerequisite.) -* At least one host exists in {Project}. (This is an obvious prerequisite.) -* Ensure the `kernelcare` package is installed on your hosts. (This prerequisite uses imperative voice.) -* Install the `kernelcare` package on your hosts. (This prerequisite is phrase like a procedure step.) +2. If a section titled `.Prerequisites` exists in the file, ensure it uses consistent formatting as described in the Overview. +3. If a section titled `.Prerequisites` exists in the file, ensure it contains information suitable for prerequisites. +4. If a procedure module does not include a `.Prerequisites` section, scan the module to identify steps that meet criteria for prerequisites. If such steps exist, create a `.Prerequisites` section and rephrase the steps as prerequisites. diff --git a/.claude/skills/refactor-adoc/SKILL.md b/.claude/skills/refactor-adoc/SKILL.md index ea3a488c485..74969815467 100644 --- a/.claude/skills/refactor-adoc/SKILL.md +++ b/.claude/skills/refactor-adoc/SKILL.md @@ -7,15 +7,25 @@ disable-model-invocation: true #### Overview -Change the title (if present), ID (if present), and file name of an assembly, module, or snippet according to a new title. -Update the includes and any ID references across all documentation. - -Usage: +This command changes the title, ID, and filename of an assembly, module, or snippet according to a new title, and updates all includes and ID references across the documentation. +**Usage:** ``` /refactor-adoc @old-file.adoc "New title" ``` +**What it does:** +- Renames the file with the appropriate prefix (e.g., `proc_new-title.adoc`) +- Updates the ID if present (e.g., `[id="new-title_{context}"]`) +- Updates the title if present (e.g., `= New title`) +- Updates all `include::` directives that reference this file +- Updates all cross-references to the old ID throughout the documentation + +**When to use:** +- When you need to rename a documentation file to better match its content +- After significantly revising the content of a module +- When improving heading clarity requires filename changes + #### Instructions Refactor the following `.adoc` file according to the following title. diff --git a/.claude/skills/review-assembly-user-story/SKILL.md b/.claude/skills/review-assembly-user-story/SKILL.md index 9d6d7ea04a6..f94a68aca77 100644 --- a/.claude/skills/review-assembly-user-story/SKILL.md +++ b/.claude/skills/review-assembly-user-story/SKILL.md @@ -6,19 +6,33 @@ description: Review assembly to ensure it follows the one-user-story principle #### Overview -Review an assembly file to ensure it describes a single user story. -If the assembly contains multiple user stories, split it into separate assembly files. - -Usage: +An assembly must cover a single user story - what the user wants to accomplish. When an assembly attempts to describe multiple user stories, it often loses focus, becomes too long, and can be confusing to follow. +**Usage:** ``` /review-assembly-user-story @assembly_example.adoc ``` -#### Reasoning +**The one-user-story principle:** +- Each assembly should answer "What does the user want to accomplish?" +- All modules in an assembly should support the same goal +- Think from the user's perspective, not the product's features + +**When an assembly needs splitting:** +- It contains procedures for multiple independent tasks that users might want to do separately +- The concept module describes multiple distinct use cases or workflows +- Different sections serve different user goals +- Modules could be logically grouped into 2 or more cohesive assemblies + +**When an assembly is fine:** +- All procedures work toward a single user goal +- Procedures are sequential steps or alternative approaches for the same task +- Modules provide context, reference, or examples for one user story -An assembly must cover a single user story (what the user wants to accomplish). -When an assembly attempts to describe multiple user stories, it often loses its focus, becomes too long, and can be confusing to follow. +**Important considerations:** +- **Inverse operations belong together** - Creating and deleting, or enabling and disabling, are part of the same user story +- **Alternative methods belong together** - Multiple procedures for the same task (web UI, CLI, API) belong in the same assembly +- **Sequential workflows belong together** - If steps must be done in order for one goal, they belong in the same assembly #### Instructions @@ -69,19 +83,15 @@ Provide a summary that includes: - If splitting occurred, list the new assembly files created and their user stories - Any recommendations for improving the assembly structure -#### Principles - -- **One user story per assembly** - Each assembly should answer "What does the user want to accomplish?" -- **User-centric organization** - Think from the user's perspective, not the product's features -- **Cohesive modules** - All modules in an assembly should support the same goal - #### Examples -##### Good examples (single user story): +**Good examples (single user story):** - `assembly_backing-up-server-and-proxy.adoc` - User wants to back up their system - `assembly_configuring-email-notifications.adoc` - User wants to set up email notifications +- `assembly_managing-organizations.adoc` - User wants to create and delete organizations (inverse operations belong together) -##### Important considerations: -- **Inverse operations belong together** - Creating and deleting (e.g., organizations), or enabling and disabling (e.g., external authentication) are part of the same user story, as users may want to revert their actions -- **Alternative methods belong together** - Multiple procedures for the same task (web UI, CLI, API) belong in the same assembly -- **Sequential workflows belong together** - If steps must be done in order for one goal, they belong in the same assembly +#### Principles + +- **One user story per assembly** - Each assembly should answer "What does the user want to accomplish?" +- **User-centric organization** - Think from the user's perspective, not the product's features +- **Cohesive modules** - All modules in an assembly should support the same goal diff --git a/.claude/skills/split-web-ui-cli/SKILL.md b/.claude/skills/split-web-ui-cli/SKILL.md index 7a73cd1dcbf..509b8c120ef 100644 --- a/.claude/skills/split-web-ui-cli/SKILL.md +++ b/.claude/skills/split-web-ui-cli/SKILL.md @@ -7,7 +7,27 @@ disable-model-invocation: true #### Overview -This file includes a web UI procedure (`.Procedure`) and a CLI procedure (`.CLI procedure`). Split it into two files: `proc_*-by-using-web-ui.adoc` and `proc_*-by-using-cli.adoc`. +When a procedure module contains both web UI steps (`.Procedure`) and CLI steps (`.CLI procedure`) in the same file, it should be split into two separate files for better modularity and clarity. + +**Usage:** +``` +/split-web-ui-cli @proc_example.adoc +``` + +**What it creates:** +- `proc_original-name-by-using-web-ui.adoc` - Contains the web UI procedure +- `proc_original-name-by-using-cli.adoc` - Contains the CLI procedure + +**File structure:** +- Both files include the introduction text from the original file +- Both files have adjusted IDs: `[id="original-id-by-using-web-ui"]` and `[id="original-id-by-using-cli"]` +- Both files have adjusted headings: `= Original heading by using {ProjectWebUI}` and `= Original heading by using Hammer CLI` +- Both files have adjusted abstracts if needed + +**When to use:** +- When a single procedure file contains both `.Procedure` and `.CLI procedure` sections +- When you want to make procedures more modular and easier to maintain +- When users need to choose between different interfaces for the same task #### Instructions diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index 2748b4e3b28..fc17b5ffb2d 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -22,6 +22,53 @@ def strip_frontmatter(content) content.sub(/\A---\s*\n.*?\n---\s*\n/m, '') end +def extract_guide_sections(content) + # Extract only sections meant for the guide (#### Overview and #### Examples) + lines = content.lines + result = [] + capturing = false + section_content = [] + + lines.each do |line| + # Check if this is a level-4 heading + if line =~ /^####\s+(.+)$/ + heading = $1.strip + + # Save previous section if we were capturing + if capturing && !section_content.empty? + result.concat(section_content) + section_content = [] + end + + # Start capturing if this is Overview or Examples (case-insensitive, flexible) + if heading =~ /^Overview$/i || heading =~ /^Examples/i + capturing = true + section_content << line + else + capturing = false + end + # Check if this is a heading of level 1-3 (stops any section) + elsif line =~ /^#\{1,3\}\s+/ + # Save previous section if we were capturing + if capturing && !section_content.empty? + result.concat(section_content) + section_content = [] + end + capturing = false + # Regular content line + elsif capturing + section_content << line + end + end + + # Don't forget the last section + if capturing && !section_content.empty? + result.concat(section_content) + end + + result.join +end + def extract_frontmatter_field(content, field) match = content.match(/\A---\s*\n(.*?)\n---\s*\n/m) return nil unless match @@ -53,6 +100,7 @@ def categorize_skill(skill_dir_name) def read_skill_files skills = [] + skipped = [] return skills unless Dir.exist?(SKILLS_DIR) # Look for skills: .claude/skills/skill-name/SKILL.md @@ -62,14 +110,29 @@ def read_skill_files skill_name = extract_frontmatter_field(content, 'name') || skill_dir_name content = strip_frontmatter(content) + # Extract only guide-relevant sections (Overview and Examples) + guide_content = extract_guide_sections(content) + + # Skip skills that have no guide content + if guide_content.strip.empty? + skipped << skill_name + next + end + skills << { name: skill_name, dir_name: skill_dir_name, category: categorize_skill(skill_dir_name), - content: content + content: guide_content } end + # Report skipped skills + unless skipped.empty? + puts " - Skipped #{skipped.length} skill(s) without Overview or Examples sections:" + skipped.each { |name| puts " - #{name}" } + end + skills end From 5d5949dd8518137b2d29c22fa58f64d6500600f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 17:20:16 +0200 Subject: [PATCH 13/19] Rename skill categories --- guides/doc-Contributing/build.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index fc17b5ffb2d..0d44a7f9a40 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -86,13 +86,13 @@ def extract_frontmatter_field(content, field) def categorize_skill(skill_dir_name) # Map skill directory names to categories categories = { - 'abstract' => 'AI skills: Style Guidelines', - 'heading' => 'AI skills: Style Guidelines', - 'prerequisites' => 'AI skills: Style Guidelines', - 'review-assembly-user-story' => 'AI skills: Content Structure', - 'split-web-ui-cli' => 'AI skills: Content Structure', - 'refactor-adoc' => 'AI skills: File Management', - 'validate-contribution' => 'AI skills: Validation and Review' + 'abstract' => 'AI skills for style guidelines', + 'heading' => 'AI skills for style guidelines', + 'prerequisites' => 'AI skills for style guidelines', + 'review-assembly-user-story' => 'AI skills for structure', + 'split-web-ui-cli' => 'AI skills for structure', + 'refactor-adoc' => 'AI skills for file management', + 'validate-contribution' => 'AI skills for contribution guidelines' } categories[skill_dir_name] || 'Other' @@ -186,7 +186,7 @@ def build_markdown skills_by_category = skills.group_by { |skill| skill[:category] } # Define category order for consistent presentation - category_order = ['AI skills: Style Guidelines', 'AI skills: Content Structure', 'AI skills: File Management', 'AI skills: Validation and Review', 'Other'] + category_order = ['AI skills for style guidelines', 'AI skills for structure', 'AI skills for file management', 'AI skills for contribution guidelines', 'Other'] category_order.each do |category| next unless skills_by_category[category] From 207db24eb9e2186c4ddee333ee159116043a85c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 17:22:14 +0200 Subject: [PATCH 14/19] Reorganize refactor-adoc skill --- .claude/skills/refactor-adoc/SKILL.md | 2 +- guides/doc-Contributing/build.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/skills/refactor-adoc/SKILL.md b/.claude/skills/refactor-adoc/SKILL.md index 74969815467..62f80b9de93 100644 --- a/.claude/skills/refactor-adoc/SKILL.md +++ b/.claude/skills/refactor-adoc/SKILL.md @@ -1,5 +1,5 @@ --- -name: refactor-adoc +name: Rename a module description: Refactor adoc file by a given title disable-model-invocation: true --- diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index 0d44a7f9a40..0f124d9e6b3 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -90,7 +90,7 @@ def categorize_skill(skill_dir_name) 'heading' => 'AI skills for style guidelines', 'prerequisites' => 'AI skills for style guidelines', 'review-assembly-user-story' => 'AI skills for structure', - 'split-web-ui-cli' => 'AI skills for structure', + 'split-web-ui-cli' => 'AI skills for file management', 'refactor-adoc' => 'AI skills for file management', 'validate-contribution' => 'AI skills for contribution guidelines' } From 089ef5b975c51bb2236fa84c1124978ec0d01dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 17:30:21 +0200 Subject: [PATCH 15/19] Improve Vale rules presentation in Contributors' Guide - Extract YAML comment descriptions as Overview sections for Vale rules - Update Vale rule descriptions to imperative voice: - "Use attributes instead of branded terms" - "Use proper capitalization for product names and technical terms" - "Write one sentence per line" - Rename category to "Foreman-documentation custom Vale rules" - Add skip notification for skills without Overview/Examples sections - Match formatting style with AI skills section (H1 categories, H2 items) Vale rules now have the same human-friendly structure as AI skills, with Overview sections explaining the rules in user-directed language. Co-Authored-By: Claude Sonnet 4.5 --- .../AvoidBrandedTerminology.yml | 2 +- .../foreman-documentation/Capitalization.yml | 2 +- .../OneSentencePerLine.yml | 2 +- guides/doc-Contributing/build.rb | 43 ++++++++++++++++--- 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml b/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml index 84680352d8a..0d542a72ec5 100644 --- a/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml +++ b/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml @@ -1,4 +1,4 @@ -# Suggest a replacement for downstream branded terms. +# Do not use branded terms in documentation. --- extends: substitution level: error diff --git a/.vale/styles/foreman-documentation/Capitalization.yml b/.vale/styles/foreman-documentation/Capitalization.yml index 7c6ce9104c9..a2a18f9f984 100644 --- a/.vale/styles/foreman-documentation/Capitalization.yml +++ b/.vale/styles/foreman-documentation/Capitalization.yml @@ -1,4 +1,4 @@ -# Suggest proper capitalization +# Use proper capitalization for product names and technical terms. --- extends: substitution ignorecase: false diff --git a/.vale/styles/foreman-documentation/OneSentencePerLine.yml b/.vale/styles/foreman-documentation/OneSentencePerLine.yml index 0f5f46f1443..0d099f1fe81 100644 --- a/.vale/styles/foreman-documentation/OneSentencePerLine.yml +++ b/.vale/styles/foreman-documentation/OneSentencePerLine.yml @@ -1,4 +1,4 @@ -# Report that a line includes more than one sentence. +# Write one sentence per line. --- extends: occurrence message: "Write one sentence per line." diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index 0f124d9e6b3..a113917a502 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -144,9 +144,29 @@ def read_vale_rules rule_name = File.basename(rule_file, '.yml') content = File.read(rule_file) + # Extract description from YAML comments at the top + description = [] + yaml_content = [] + in_yaml = false + + content.lines.each do |line| + if line.strip.start_with?('#') && !in_yaml + # Comment line before YAML starts + description << line.sub(/^#\s*/, '').strip + elsif line.strip == '---' + # YAML document start + in_yaml = true + yaml_content << line + elsif in_yaml + # YAML content + yaml_content << line + end + end + rules << { name: rule_name, - content: content + description: description.join(' '), + yaml: yaml_content.join } end @@ -212,22 +232,35 @@ def build_markdown # Add Vale rules section rules = read_vale_rules unless rules.empty? - markdown << "# Project-Specific Vale Rules" + markdown << "# Foreman-documentation custom Vale rules" markdown << "" markdown << "The following custom Vale rules enforce documentation standards specific to Foreman." - markdown << "These rules are located in `.vale/styles/foreman-documentation/`." + markdown << "These can be invoked in AI-assisted editors like Claude Code or Cursor." markdown << "" rules.each do |rule| - markdown << "## Rule: #{rule[:name]}" + markdown << "## #{rule[:name]}" markdown << "" + + # Add Overview section if description exists + unless rule[:description].empty? + markdown << "#### Overview" + markdown << "" + markdown << rule[:description] + markdown << "" + end + + # Add the YAML rule markdown << "**File:** `.vale/styles/foreman-documentation/#{rule[:name]}.yml`" markdown << "" markdown << "```yaml" - markdown << rule[:content] + markdown << rule[:yaml] markdown << "```" markdown << "" end + + markdown << "---" + markdown << "" end markdown.join("\n") From a5698784800262873632c3e4c4bf696493f98a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 17:32:59 +0200 Subject: [PATCH 16/19] Expand Vale rule descriptions and link to files instead of embedding - Expand Vale rule Overview sections with detailed explanations: - AvoidBrandedTerminology: Explain attribute usage for multi-product docs - Capitalization: Include examples and context exceptions - OneSentencePerLine: Explain benefits for version control and review - Replace embedded YAML code blocks with links to rule files - Keep guide focused on guidelines rather than technical implementation This makes the Contributors' Guide more readable while still providing access to the detailed rule definitions via links. Co-Authored-By: Claude Sonnet 4.5 --- .../AvoidBrandedTerminology.yml | 2 +- .../styles/foreman-documentation/Capitalization.yml | 2 +- .../foreman-documentation/OneSentencePerLine.yml | 2 +- guides/doc-Contributing/build.rb | 12 +++--------- 4 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml b/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml index 0d542a72ec5..f7c92c66fdf 100644 --- a/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml +++ b/.vale/styles/foreman-documentation/AvoidBrandedTerminology.yml @@ -1,4 +1,4 @@ -# Do not use branded terms in documentation. +# Do not use branded terms in documentation. Use AsciiDoc attributes like {Project}, {ProjectServer}, and {SmartProxy} instead of product-specific names like "Satellite", "orcharhino", or "Capsule". This ensures the documentation works for all build targets. --- extends: substitution level: error diff --git a/.vale/styles/foreman-documentation/Capitalization.yml b/.vale/styles/foreman-documentation/Capitalization.yml index a2a18f9f984..924a25015c1 100644 --- a/.vale/styles/foreman-documentation/Capitalization.yml +++ b/.vale/styles/foreman-documentation/Capitalization.yml @@ -1,4 +1,4 @@ -# Use proper capitalization for product names and technical terms. +# Use proper capitalization for product names and technical terms. For example, write "Ansible" not "ansible", "PostgreSQL" not "postgresql", and "lifecycle environment" not "Lifecycle Environment". Different capitalization may be required in specific contexts like Web UI buttons, settings, or templates. --- extends: substitution ignorecase: false diff --git a/.vale/styles/foreman-documentation/OneSentencePerLine.yml b/.vale/styles/foreman-documentation/OneSentencePerLine.yml index 0d099f1fe81..3b92e811b0d 100644 --- a/.vale/styles/foreman-documentation/OneSentencePerLine.yml +++ b/.vale/styles/foreman-documentation/OneSentencePerLine.yml @@ -1,4 +1,4 @@ -# Write one sentence per line. +# Write one sentence per line. This makes diffs easier to read, simplifies reviewing changes, and helps track modifications to individual sentences. End each sentence with proper punctuation (period, question mark, or exclamation point) before starting a new line. --- extends: occurrence message: "Write one sentence per line." diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index a113917a502..32569f085b2 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -242,20 +242,14 @@ def build_markdown markdown << "## #{rule[:name]}" markdown << "" - # Add Overview section if description exists + # Add description if it exists unless rule[:description].empty? - markdown << "#### Overview" - markdown << "" markdown << rule[:description] markdown << "" end - # Add the YAML rule - markdown << "**File:** `.vale/styles/foreman-documentation/#{rule[:name]}.yml`" - markdown << "" - markdown << "```yaml" - markdown << rule[:yaml] - markdown << "```" + # Link to the YAML file instead of embedding it + markdown << "**Rule file:** [`.vale/styles/foreman-documentation/#{rule[:name]}.yml`](../../.vale/styles/foreman-documentation/#{rule[:name]}.yml)" markdown << "" end From b133619d580cd96ad21679d19511bc2c145094d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 18:03:48 +0200 Subject: [PATCH 17/19] Split and restructure validate-contribution skill - Create new "personas" skill for user persona guidelines - Overview explains User, Admin, and Architect personas - Instructions for applying persona-appropriate content - Restructure "validate-contribution" skill as "Documentation conventions" - Add comprehensive Overview section covering all conventions - Add Examples section with good/bad examples - Keep AI validation instructions in Instructions section - Improve code block handling in build script - Now properly appears in Contributors' Guide - Update build.rb to include personas in style guidelines category Both skills now follow the standard structure with Overview and Examples sections for the Contributors' Guide, while keeping detailed AI instructions separate. Co-Authored-By: Claude Sonnet 4.5 --- .claude/skills/personas/SKILL.md | 39 +++ .claude/skills/validate-contribution/SKILL.md | 263 +++++------------- guides/doc-Contributing/build.rb | 15 + 3 files changed, 129 insertions(+), 188 deletions(-) create mode 100644 .claude/skills/personas/SKILL.md diff --git a/.claude/skills/personas/SKILL.md b/.claude/skills/personas/SKILL.md new file mode 100644 index 00000000000..bf34525fbfa --- /dev/null +++ b/.claude/skills/personas/SKILL.md @@ -0,0 +1,39 @@ +--- +name: User personas +description: Understand and apply Foreman user personas when writing documentation +--- +### User personas + +#### Overview + +Foreman documentation targets different user personas with varying responsibilities and permissions. Understanding the target persona helps ensure documentation addresses the user's needs and capabilities appropriately. + +**User persona:** +- Has limited permissions +- Runs regular Foreman operations +- Example responsibilities: managing content, provisioning hosts, managing hosts + +**Admin persona:** +- Has unlimited permissions, including root access to the Foreman Server +- Example responsibilities: managing Foreman server, configuring system settings + +**Architect persona:** +- Has no permissions, does not perform practical administrative or management tasks +- Example responsibilities: evaluating whether Foreman/Katello meets organizational needs, planning deployment architecture + +**When to consider personas:** +- Use persona-appropriate language and assume persona-appropriate knowledge +- For User persona: Focus on tasks they can perform with limited permissions +- For Admin persona: Include system administration and configuration tasks +- For Architect persona: Provide planning, architecture, and decision-making information + +#### Instructions + +When reviewing or writing documentation, identify the target persona and ensure: + +1. The content matches the persona's permission level and responsibilities +2. Technical depth is appropriate for the persona's expertise +3. Prerequisites assume the persona's typical environment +4. Examples and use cases reflect the persona's real-world scenarios + +If content targets multiple personas, consider splitting it or clearly indicating which sections apply to which personas. diff --git a/.claude/skills/validate-contribution/SKILL.md b/.claude/skills/validate-contribution/SKILL.md index d82756e4376..629d7d795f3 100644 --- a/.claude/skills/validate-contribution/SKILL.md +++ b/.claude/skills/validate-contribution/SKILL.md @@ -1,227 +1,114 @@ --- -name: validate-contribution -description: Validate and auto-fix documentation contributions against project guidelines +name: Documentation conventions +description: Validate and apply Foreman documentation conventions disable-model-invocation: false --- -## Foreman documentation conventions guide +### Foreman documentation conventions -### Code conventions +#### Overview -Use the following markup conventions: +Foreman documentation follows specific conventions for code, images, attributes, conditionals, and file structure. These conventions ensure consistency across all guides and enable multi-product builds from a single source. -* Use UTF-8 character encoding in source files. -* Do not add trailing whitespace on lines and in files. -Some editors can help with this. -For example, VS Code has multiple settings related to handling whitespaces. -Whitespace after partial files has to be handled in the file using the `include::` directive. -* Surround user input with underscores (`_`) to indicate variable input, for example, `hammer organization create --name "_My_Organization_"`. +**Code conventions:** +- Use UTF-8 character encoding in source files +- Do not add trailing whitespace on lines or in files +- Surround user input with underscores to indicate variable input (e.g., `hammer organization create --name "_My_Organization_"`) -### Images +**Images:** +- Save guide-specific images to `guides/doc-/images/` +- Save shared images to `guides/common/images/` +- Create editable diagrams using [diagrams.net](https://www.diagrams.net/) in `drawio` format, place in `guides/image-sources/`, export to SVG -Each guide directory contains an `images/` subdirectory with `images/common` symlink into the `common/images/` directory. +**AsciiDoc attributes:** +- Use attributes instead of hardcoded product names: `{Project}`, `{ProjectServer}`, `{SmartProxy}` instead of "Foreman", "Satellite", "Capsule" +- To use attributes in code blocks, add `subs="+quotes,attributes"` option +- Attribute files: `attributes.adoc`, `attributes-base.adoc`, `attributes-foreman-el.adoc`, `attributes-foreman-deb.adoc`, `attributes-katello.adoc`, `attributes-satellite.adoc`, `attributes-orcharhino.adoc` -* Save images local to the guide to the `images/` directory. -* Save images which are supposed to be reused across guides to the `images/common/` directory. +**Conditional content:** +- Use `ifdef::katello[]` to show content only for specific builds +- Use `ifndef::satellite[]` to hide content for specific builds +- Use comma for logic "or": `ifdef::katello,satellite[]` +- For context-specific content, combine `ifdef` and `ifeval` -You can create upstream diagrams using [diagrams.net](https://www.diagrams.net/). -Place the editable diagram in `drawio` format in `guides/image-sources/`. -For inclusion in the content, export diagrams to SVG and place them as described above. +**File structure:** +- Follow the [Modular documentation framework](https://redhat-documentation.github.io/modular-docs/) +- **Assemblies** (`assembly_*.adoc`): User stories at the top of `common/` - do not nest assemblies +- **Concept modules** (`con_*.adoc`): Explain what and why, start with `:_mod-docs-content-type: CONCEPT` +- **Procedure modules** (`proc_*.adoc`): Explain how, start with `:_mod-docs-content-type: PROCEDURE` +- **Reference modules** (`ref_*.adoc`): Tables and options, start with `:_mod-docs-content-type: REFERENCE` +- **Snippets** (`snip_*.adoc`): Reusable text fragments without IDs -### AsciiDoc attributes for different build targets +#### Examples -Because the content in this repository is shared between the upstream Foreman community and branded downstream products, many terms need to be written using AsciiDoc attributes. -For example, never write "Foreman", "Satellite", or "orcharhino" words directly, but use the `{Project}` attribute. - -The attributes used in this repository are defined in the following files: - -* [attributes.adoc](common/attributes.adoc): version definitions and includes for other attribute files. -* [attributes-base.adoc](common/attributes-base.adoc): base attributes common for all builds. -* [attributes-foreman-el.adoc](common/attributes-foreman-el.adoc): base overrides for foreman-el build. -* [attributes-foreman-deb.adoc](common/attributes-foreman-deb.adoc): base overrides for foreman-deb build. -* [attributes-katello.adoc](common/attributes-katello.adoc): base overrides for katello build. -* [attributes-satellite.adoc](common/attributes-satellite.adoc): base overrides for satellite build. -* [attributes-orcharhino.adoc](common/attributes-orcharhino.adoc): base overrides for orcharhino build. - -By default, attributes cannot be used in shell or code examples. -To use them, use the "attributes" keyword: - - [options="nowrap" subs="+quotes,attributes"] - ---- - # ls {AttributeName} - ---- - -### Conditional content - -If a piece of your content, such as a block, paragraph, warning, or chapter, is specific for a certain build target, use AsciiDoc conditionals to show or hide it. - -To show a piece of content only for the `katello` build: - - ifdef::katello[] - NOTE: This part is only relevant for Foreman with the Katello plugin. - endif::[] - -To hide a piece of content for `katello` but show it for all other builds: - - ifndef::katello[] - NOTE: This part is relevant for Foreman without the Katello plugin, but also Satellite and orcharhino. - endif::[] - -Use comma for logic "or": - - ifdef::katello,satellite[] - NOTE: This part is only relevant for deployments with Katello plugin or in Satellite environment. - endif::[] - -Some files are included in different contexts, there are attributes to find the correct context. -In these cases use both `ifdef` and `ifeval`: - - ifdef::foreman-el,foreman-deb[] - ifeval::["{context}" == "{project-context}"] - * A minimum of 4 GB RAM is required for {ProjectServer} to function. - endif::[] - endif::[] - -### File structure - -If you create a new file, use the file structure described here. - -Documentation in this directory follows a modular structure described in the [Modular documentation reference guide](https://redhat-documentation.github.io/modular-docs/). -To write new documentation, you can use [modular documentation templates](https://github.com/redhat-documentation/modular-docs/tree/main/modular-docs-manual/files) or copy an existing file from `guides/common/modules/` and adapt it. - -Included files are kept in the `common/` subdirectory and have prefixes to distinguish their type of content. - -Assemblies are kept at the top of the `common/` subdirectory: - -* [`assembly`](https://redhat-documentation.github.io/modular-docs/#forming-assemblies): Files starting with `assembly_` contain user stories and the modules required to accomplish those user stories. -See the [assembly template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_ASSEMBLY_a-collection-of-modules.adoc). -* In this repository, do not nest assemblies. This means that assemblies cannot contain includes of other assemblies. This guidance overrides the Modular documentation recommendations. -* Do not include assemblies without leveloffset or with leveloffset of two or more in `master.adoc` files. - -Modules are kept in the `common/modules/` subdirectory: - -* [`con`](https://redhat-documentation.github.io/modular-docs/#creating-concept-modules): Files starting with `con_` contain concepts and explain the _what_ and _why_. -Their first line contains the `:_mod-docs-content-type: CONCEPT` attribute. -See the [concept template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_CONCEPT_concept-explanation.adoc). -* [`proc`](https://redhat-documentation.github.io/modular-docs/#creating-procedure-modules): Files starting with `proc_` contain procedures and explain _how_ to achieve a specific goal. -Their first line contains the `:_mod-docs-content-type: PROCEDURE` attribute. -See the [procedure template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_PROCEDURE_doing-one-procedure.adoc). -* [`ref`](https://redhat-documentation.github.io/modular-docs/#creating-reference-modules): Files starting with `ref_` contain references and append other files, for example tables with options. -Their first line contains the `:_mod-docs-content-type: REFERENCE` attribute. -See the [reference template](https://raw.githubusercontent.com/redhat-documentation/modular-docs/master/modular-docs-manual/files/TEMPLATE_REFERENCE_reference-material.adoc). -* [`snip`](https://redhat-documentation.github.io/modular-docs/#using_text_snippets_or_text_fragments_writing-mod-docs): Files starting with `snip_` contain snippets that are reused throughout multiple guides, for example admonitions. -Snippets must not contain an ID. - -### Foreman user personas - -In documentation, a user persona is the target user who will be reading the documentation. -Understanding and identifying the target persona of a piece of content helps ensure that the documentation will properly address the user's needs and capabilities. - -Foreman users include people with varying responsibilities and permissions. -Especially in larger organizations, different tasks are performed by different teams. -Therefore, when contributing to Foreman documentation, it can be useful to be aware of and distinguish Foreman user personas. - -#### *User* persona - -* Has limited permissions -* Runs regular Foreman operations -* Example responsibilities: managing content, provisioning hosts, and managing hosts - -#### *Admin* persona - -* Has unlimited permissions, including root access to the Foreman Server -* Example responsibilities: managing Foreman server - -#### *Architect* persona - -* Has no permissions, does not perform practical administrative or management tasks -* Example responsibilities: determining whether Foreman/Katello meets the needs of their organization and planning the deployment - -### Further Information - -* [Contributing Guidelines for Github documentation](https://github.com/github/docs/blob/main/CONTRIBUTING.md) -* [theforeman.org/contribute](https://theforeman.org/contribute.html) -* [7 Git tips for technical writers](https://opensource.com/article/22/11/git-tips-technical-writers) - ---- - -## AI Instructions: Automatic Validation and Fixing - -When invoked (either manually or automatically after AI makes changes), perform the following checks and auto-fixes on all modified `.adoc` files in `guides/`: - -### 1. File Naming Validation - -**Check**: Files in `guides/common/modules/` must have correct prefixes: -- `con_*.adoc` - Concept modules -- `proc_*.adoc` - Procedure modules -- `ref_*.adoc` - Reference modules -- `snip_*.adoc` - Snippets - -**Auto-fix**: If prefix doesn't match content type attribute, rename the file and update all includes. - -### 2. Content Type Attribute - -**Check**: All modules (except snippets) must have content type on first line: -- `:_mod-docs-content-type: CONCEPT` -- `:_mod-docs-content-type: PROCEDURE` -- `:_mod-docs-content-type: REFERENCE` - -**Auto-fix**: Add missing content type attribute based on file prefix. - -### 3. Module ID Format - -**Check**: All modules (except snippets) must have ID in format `[id="title-with-dashes_{context}"]` - -**Auto-fix**: Add or fix ID to match title and include `_{context}` suffix. - -### 4. Trailing Whitespace - -**Check**: No trailing whitespace on any lines or at end of files. +**Good attribute usage:** +```asciidoc +Navigate to {ProjectWebUI} and click *Hosts*. +``` -**Auto-fix**: Remove all trailing whitespace. +**Bad (hardcoded):** +```asciidoc +Navigate to Satellite Web UI and click *Hosts*. +``` -### 5. Hardcoded Product Names +**Good conditional:** +```asciidoc +ifdef::katello[] +This feature requires the Katello plugin. +endif::[] +``` -**Check**: Scan for hardcoded product names that should use attributes: -- "Foreman" → `{Project}` or `{ProjectName}` -- "Satellite" → `{Project}` (in multi-build contexts) -- "orcharhino" → `{Project}` (in multi-build contexts) -- "Capsule" → `{SmartProxy}` or `{SmartProxyServer}` +**Good user input:** +```asciidoc +hammer organization create --name "_My_Organization_" +``` -**Auto-fix**: Replace with appropriate attribute if found in non-conditional context. +#### Instructions -### 6. Vale Linting +When invoked (manually or automatically after making changes), perform validation and auto-fixes on modified `.adoc` files in `guides/`: -**Check**: Run `vale` on modified files. +**1. File Naming Validation** +- Check: Files in `guides/common/modules/` must have correct prefixes (`con_`, `proc_`, `ref_`, `snip_`) +- Auto-fix: Rename file and update all includes if prefix doesn't match content type -**Report**: List any style violations (don't auto-fix Vale issues, just report them). +**2. Content Type Attribute** +- Check: All modules (except snippets) must have content type on first line +- Auto-fix: Add missing content type based on file prefix -### 7. Build Test +**3. Module ID Format** +- Check: All modules (except snippets) must have ID: `[id="title-with-dashes_{context}"]` +- Auto-fix: Add or fix ID to match title and include `_{context}` suffix -**Check**: Ensure modified files can build successfully. +**4. Trailing Whitespace** +- Check: No trailing whitespace on any lines or at end of files +- Auto-fix: Remove all trailing whitespace -**Report**: If build fails, show error and affected files. +**5. Hardcoded Product Names** +- Check: Scan for "Foreman", "Satellite", "orcharhino", "Capsule" in non-conditional context +- Auto-fix: Replace with appropriate attributes (`{Project}`, `{SmartProxy}`, etc.) -### Output Format +**6. Vale Linting** +- Check: Run `vale` on modified files +- Report: List style violations (don't auto-fix, just report) -After validation and fixes, provide a concise summary: +**7. Build Test** +- Check: Ensure modified files build successfully +- Report: Show errors if build fails +**Output format:** ``` ✅ Validated contribution Fixed: - Removed trailing whitespace from 3 files - Added content type attribute to proc_example.adoc - - Fixed ID format in con_overview.adoc ⚠ Warnings: - - Vale: 2 style issues in proc_example.adoc (lines 15, 23) + - Vale: 2 style issues in proc_example.adoc ✓ Build: All modified files build successfully ``` -### When NOT to Run - -Skip validation if: +**Skip validation when:** - Changes are only to non-documentation files (Makefiles, scripts, config) - Changes are only to `web/` directory -- Changes are to this CONTRIBUTING.md file itself +- Changes are to CONTRIBUTING.md diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index 32569f085b2..ba1bbb57ced 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -28,8 +28,22 @@ def extract_guide_sections(content) result = [] capturing = false section_content = [] + in_code_block = false lines.each do |line| + # Track code blocks (````) + if line.strip.start_with?('```') + in_code_block = !in_code_block + section_content << line if capturing + next + end + + # Skip heading detection inside code blocks + if in_code_block + section_content << line if capturing + next + end + # Check if this is a level-4 heading if line =~ /^####\s+(.+)$/ heading = $1.strip @@ -89,6 +103,7 @@ def categorize_skill(skill_dir_name) 'abstract' => 'AI skills for style guidelines', 'heading' => 'AI skills for style guidelines', 'prerequisites' => 'AI skills for style guidelines', + 'personas' => 'AI skills for style guidelines', 'review-assembly-user-story' => 'AI skills for structure', 'split-web-ui-cli' => 'AI skills for file management', 'refactor-adoc' => 'AI skills for file management', From ff5063696c2d4a1602ebcd6e313d814becd26877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 18:13:50 +0200 Subject: [PATCH 18/19] Fix incorrect description of Vale rule invocation in Contributors' Guide Vale rules are run by the Vale linter locally and in CI, not in AI-assisted editors. Co-authored-by: Cursor --- guides/doc-Contributing/build.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index ba1bbb57ced..c19932e8cc4 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -250,7 +250,7 @@ def build_markdown markdown << "# Foreman-documentation custom Vale rules" markdown << "" markdown << "The following custom Vale rules enforce documentation standards specific to Foreman." - markdown << "These can be invoked in AI-assisted editors like Claude Code or Cursor." + markdown << "Run the Vale linter locally or in CI to check AsciiDoc files against these rules." markdown << "" rules.each do |rule| From 0609413d8ca632a1d0759291d84c5035f59d4eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aneta=20=C5=A0teflov=C3=A1=20Petrov=C3=A1?= Date: Fri, 5 Jun 2026 18:33:38 +0200 Subject: [PATCH 19/19] Make Vale rules collapsible in Contributors' Guide Replace links to Vale rule files with embedded YAML content inside collapsible HTML
    sections. This keeps the guide concise while making full rule definitions accessible without navigation. Co-Authored-By: Claude Sonnet 4.5 --- .claude/skills/abstract/SKILL.md | 2 - .claude/skills/heading/SKILL.md | 3 - .claude/skills/personas/SKILL.md | 2 - .claude/skills/prerequisites/SKILL.md | 2 - .claude/skills/refactor-adoc/SKILL.md | 2 - .../review-assembly-user-story/SKILL.md | 2 - .claude/skills/split-web-ui-cli/SKILL.md | 2 - .claude/skills/validate-contribution/SKILL.md | 3 - guides/doc-Contributing/build.rb | 109 ++++++++++++++++-- 9 files changed, 97 insertions(+), 30 deletions(-) diff --git a/.claude/skills/abstract/SKILL.md b/.claude/skills/abstract/SKILL.md index a602ffc96fb..56f0a4e419c 100644 --- a/.claude/skills/abstract/SKILL.md +++ b/.claude/skills/abstract/SKILL.md @@ -2,8 +2,6 @@ name: Abstracts description: Review or write an abstract (also called a short description) for a documentation module --- -### Review or write abstract - #### Overview An abstract is the first paragraph of a documentation module that helps readers and AI-powered search tools find the information they need and confirm they are in the right place. diff --git a/.claude/skills/heading/SKILL.md b/.claude/skills/heading/SKILL.md index 1ed43b191b8..d73d8cdbd2f 100644 --- a/.claude/skills/heading/SKILL.md +++ b/.claude/skills/heading/SKILL.md @@ -2,9 +2,6 @@ name: Headings description: Review or write heading --- - -### Review or write heading - #### Overview Headings should be clear, concise, and use familiar keywords that help users understand what the content covers. diff --git a/.claude/skills/personas/SKILL.md b/.claude/skills/personas/SKILL.md index bf34525fbfa..9fcd4761548 100644 --- a/.claude/skills/personas/SKILL.md +++ b/.claude/skills/personas/SKILL.md @@ -2,8 +2,6 @@ name: User personas description: Understand and apply Foreman user personas when writing documentation --- -### User personas - #### Overview Foreman documentation targets different user personas with varying responsibilities and permissions. Understanding the target persona helps ensure documentation addresses the user's needs and capabilities appropriately. diff --git a/.claude/skills/prerequisites/SKILL.md b/.claude/skills/prerequisites/SKILL.md index 83b30a240a8..8348b1782dc 100644 --- a/.claude/skills/prerequisites/SKILL.md +++ b/.claude/skills/prerequisites/SKILL.md @@ -2,8 +2,6 @@ name: Prerequisites description: Review or add prerequisites --- -### Review or add prerequisites - #### Overview Prerequisites are a bulleted list of conditions that must be satisfied before the user starts a procedure. Only procedure modules (proc_*.adoc) can include a `.Prerequisites` section. diff --git a/.claude/skills/refactor-adoc/SKILL.md b/.claude/skills/refactor-adoc/SKILL.md index 62f80b9de93..d9d24f88af6 100644 --- a/.claude/skills/refactor-adoc/SKILL.md +++ b/.claude/skills/refactor-adoc/SKILL.md @@ -3,8 +3,6 @@ name: Rename a module description: Refactor adoc file by a given title disable-model-invocation: true --- -### Refactor adoc file by a given title - #### Overview This command changes the title, ID, and filename of an assembly, module, or snippet according to a new title, and updates all includes and ID references across the documentation. diff --git a/.claude/skills/review-assembly-user-story/SKILL.md b/.claude/skills/review-assembly-user-story/SKILL.md index f94a68aca77..7da366f51e3 100644 --- a/.claude/skills/review-assembly-user-story/SKILL.md +++ b/.claude/skills/review-assembly-user-story/SKILL.md @@ -2,8 +2,6 @@ name: An assembly covers a single user story description: Review assembly to ensure it follows the one-user-story principle --- -### Review assembly for single user story - #### Overview An assembly must cover a single user story - what the user wants to accomplish. When an assembly attempts to describe multiple user stories, it often loses focus, becomes too long, and can be confusing to follow. diff --git a/.claude/skills/split-web-ui-cli/SKILL.md b/.claude/skills/split-web-ui-cli/SKILL.md index 509b8c120ef..079695e58ec 100644 --- a/.claude/skills/split-web-ui-cli/SKILL.md +++ b/.claude/skills/split-web-ui-cli/SKILL.md @@ -3,8 +3,6 @@ name: Split a module into web UI and CLI modules description: Split a module into web UI and CLI modules disable-model-invocation: true --- -### Split a module into web UI and CLI modules - #### Overview When a procedure module contains both web UI steps (`.Procedure`) and CLI steps (`.CLI procedure`) in the same file, it should be split into two separate files for better modularity and clarity. diff --git a/.claude/skills/validate-contribution/SKILL.md b/.claude/skills/validate-contribution/SKILL.md index 629d7d795f3..382dd6e840d 100644 --- a/.claude/skills/validate-contribution/SKILL.md +++ b/.claude/skills/validate-contribution/SKILL.md @@ -3,9 +3,6 @@ name: Documentation conventions description: Validate and apply Foreman documentation conventions disable-model-invocation: false --- - -### Foreman documentation conventions - #### Overview Foreman documentation follows specific conventions for code, images, attributes, conditionals, and file structure. These conventions ensure consistency across all guides and enable multi-product builds from a single source. diff --git a/guides/doc-Contributing/build.rb b/guides/doc-Contributing/build.rb index c19932e8cc4..b0d1f4ab7a2 100644 --- a/guides/doc-Contributing/build.rb +++ b/guides/doc-Contributing/build.rb @@ -22,8 +22,8 @@ def strip_frontmatter(content) content.sub(/\A---\s*\n.*?\n---\s*\n/m, '') end -def extract_guide_sections(content) - # Extract only sections meant for the guide (#### Overview and #### Examples) +def extract_visible_sections(content) + # Extract sections meant to be visible (#### Overview and #### Examples) lines = content.lines result = [] capturing = false @@ -83,6 +83,67 @@ def extract_guide_sections(content) result.join end +def extract_ai_sections(content) + # Extract sections meant for AI tools (everything EXCEPT Overview and Examples) + lines = content.lines + result = [] + capturing = true # Start capturing by default + section_content = [] + in_code_block = false + + lines.each do |line| + # Track code blocks (````) + if line.strip.start_with?('```') + in_code_block = !in_code_block + section_content << line if capturing + next + end + + # Skip heading detection inside code blocks + if in_code_block + section_content << line if capturing + next + end + + # Check if this is a level-4 heading + if line =~ /^####\s+(.+)$/ + heading = $1.strip + + # Save previous section if we were capturing + if capturing && !section_content.empty? + result.concat(section_content) + section_content = [] + end + + # Stop capturing if this is Overview or Examples (opposite of visible sections) + if heading =~ /^Overview$/i || heading =~ /^Examples/i + capturing = false + else + capturing = true + section_content << line + end + # Check if this is a heading of level 1-3 (stops any section) + elsif line =~ /^#\{1,3\}\s+/ + # Save previous section if we were capturing + if capturing && !section_content.empty? + result.concat(section_content) + section_content = [] + end + capturing = false + # Regular content line + elsif capturing + section_content << line + end + end + + # Don't forget the last section + if capturing && !section_content.empty? + result.concat(section_content) + end + + result.join +end + def extract_frontmatter_field(content, field) match = content.match(/\A---\s*\n(.*?)\n---\s*\n/m) return nil unless match @@ -125,11 +186,14 @@ def read_skill_files skill_name = extract_frontmatter_field(content, 'name') || skill_dir_name content = strip_frontmatter(content) - # Extract only guide-relevant sections (Overview and Examples) - guide_content = extract_guide_sections(content) + # Extract sections for human readers (Overview and Examples) + visible_content = extract_visible_sections(content) - # Skip skills that have no guide content - if guide_content.strip.empty? + # Extract sections for AI tools (everything else) + ai_content = extract_ai_sections(content) + + # Skip skills that have no content at all + if visible_content.strip.empty? && ai_content.strip.empty? skipped << skill_name next end @@ -138,13 +202,14 @@ def read_skill_files name: skill_name, dir_name: skill_dir_name, category: categorize_skill(skill_dir_name), - content: guide_content + visible_content: visible_content, + ai_content: ai_content } end # Report skipped skills unless skipped.empty? - puts " - Skipped #{skipped.length} skill(s) without Overview or Examples sections:" + puts " - Skipped #{skipped.length} skill(s) without any content:" skipped.each { |name| puts " - #{name}" } end @@ -235,8 +300,23 @@ def build_markdown skills_by_category[category].each do |skill| markdown << "## #{skill[:name]}" markdown << "" - markdown << skill[:content] - markdown << "" + + # Add visible content (Overview and Examples) first + unless skill[:visible_content].strip.empty? + markdown << skill[:visible_content] + markdown << "" + end + + # Add AI-specific content (Instructions, etc.) in a collapsible section + unless skill[:ai_content].strip.empty? + markdown << "
    " + markdown << "View AI tool instructions" + markdown << "" + markdown << skill[:ai_content] + markdown << "" + markdown << "
    " + markdown << "" + end end markdown << "---" @@ -263,8 +343,13 @@ def build_markdown markdown << "" end - # Link to the YAML file instead of embedding it - markdown << "**Rule file:** [`.vale/styles/foreman-documentation/#{rule[:name]}.yml`](../../.vale/styles/foreman-documentation/#{rule[:name]}.yml)" + # Embed the YAML content in a collapsible section + markdown << "
    " + markdown << "View rule definition" + markdown << "" + markdown << "
    #{rule[:yaml]}
    " + markdown << "" + markdown << "
    " markdown << "" end