From cqa-tools
Assesses CQA P2-P7 modularization in Red Hat AsciiDoc docs: assembly structure without rendered text between includes, module prefixes, templates, required elements, nesting depth.
npx claudepluginhub redhat-documentation/redhat-docs-agent-tools --plugin cqa-toolsThis skill is limited to using the following tools:
| # | Parameter | Level |
Reviews AsciiDoc (.adoc) files for Red Hat modular documentation compliance: module types (concept, procedure, reference), assembly structure, anchor IDs with _{context}, context variables, and include directives.
Assesses CQA parameters P8-P11 for titles and short descriptions in Red Hat modular documentation, checking clarity, character limits, DITA conventions, and quality criteria.
Validates documentation quality for research software using Vale prose linting, HTMLProofer link checking, markdownlint Markdown validation, code example testing, container instructions, and CI integration.
Share bugs, ideas, or general feedback.
| # | Parameter | Level |
|---|---|---|
| P2 | Assemblies contain only intro + includes (no rendered text between includes) | Required |
| P3 | Content is modularized (correct prefixes: assembly_, con_, proc_, ref_, snip_) | Required |
| P4 | Modules use official templates (Concept, Procedure, Reference) | Required |
| P5 | All required modular elements present (content type, ID, title, abstract) | Required |
| P6 | Assemblies use official template | Required |
| P7 | Content not deeply nested (max 3 levels: master -> assembly -> topic) | Important |
This skill has an automation script:
| Script | Parameters | What it checks |
|---|---|---|
check-content-types.py | P3, P4, P5 | Prefix vs content type match, required elements, invalid block titles, procedure structure |
Python 3.9+ stdlib only, no dependencies. Exit code 0 = pass, 1 = issues found.
python3 ${CLAUDE_PLUGIN_ROOT}/skills/cqa-assess/scripts/check-content-types.py "$DOCS_REPO"
Checks: filename prefix matches :_mod-docs-content-type:, [role="_abstract"] present, [id="..._{context}"] present, no procedure-only block titles in non-procedure files, no == subsections in procedures, ordered list after .Procedure.
Ask the user for the path to their Red Hat modular documentation repository. This is the directory that contains assemblies/, topics/, and titles/ directories.
Store this as DOCS_REPO for all subsequent steps.
Assemblies map to DITA maps. DITA maps do not accept rendered text between module includes.
An assembly has three sections in strict order:
include::) — metadata, title, abstract, and one or more paragraphs, admonition blocks, and/or lists. All rendered text must appear here.include:: directives for topics, separated only by blank lines and AsciiDoc comments (// ...). No rendered text is allowed between includes.[role="_additional-resources"] .Additional resources section with links.For each assembly_*.adoc file in assemblies/:
include:: directiveinclude:: directiveinclude:: — only the following are allowed:
include:: directives// ...)Move all rendered text that appears between includes to the introductory section before the first include::. If the text is specific to a particular topic, consider absorbing it into that topic's abstract or content instead.
| Score | Criteria |
|---|---|
| 4 | All assemblies have no rendered text between includes |
| 3 | 1-2 assemblies with minor text between includes (e.g., a single comment-like sentence) |
| 2 | Multiple assemblies with paragraphs, lists, or admonitions between includes |
| 1 | Assembly structure not assessed or widespread violations |
Reference: https://redhat-documentation.github.io/modular-docs/
Content is modularized when it follows the Red Hat modular documentation framework:
include:: directives.:_mod-docs-content-type: attribute, the filename prefix, and the actual content must all agree.Ask the user for the directory structure of their docs repo. The typical Red Hat modular docs repo has assemblies/, topics/ (or modules/), and snippets/ directories.
For each .adoc file, verify it uses the correct prefix:
| Directory | Required prefix(es) |
|---|---|
| Assemblies directory | assembly_ |
| Topics/modules directory (concepts) | con_ |
| Topics/modules directory (procedures) | proc_ |
| Topics/modules directory (references) | ref_ |
| Snippets directory | snip_ |
List all files and flag any that don't match the expected prefix pattern.
For each .adoc file in the assemblies and topics directories, read the first line and check for :_mod-docs-content-type: attribute. Valid values: ASSEMBLY, CONCEPT, PROCEDURE, REFERENCE, SNIPPET.
Flag any files that:
:_mod-docs-content-type: declarationFor each file, verify the filename prefix matches the declared content type:
| Prefix | Expected :_mod-docs-content-type: |
|---|---|
assembly_ | ASSEMBLY |
con_ | CONCEPT |
proc_ | PROCEDURE |
ref_ | REFERENCE |
snip_ | SNIPPET |
Flag any mismatches.
Verify the declared content type matches what the file actually contains:
| Content type | Must contain | Must NOT contain |
|---|---|---|
| PROCEDURE | .Procedure section with ordered list steps (. ) | — |
| CONCEPT | Explanatory/descriptive content | .Procedure section |
| REFERENCE | Structured data (tables, lists, source blocks) | .Procedure section |
| ASSEMBLY | include:: directives | .Procedure section |
Check ALL procedure files for .Procedure with ordered steps. Check ALL concept files to confirm they have no .Procedure section. Check ALL reference files to confirm they contain structured data.
Reference:
Titles must be brief, complete, and descriptive. Assess three dimensions:
Check 5a: Grammatical form
| Module type | Required form | Examples |
|---|---|---|
| PROCEDURE | Imperative phrase (verb) | "Configure OAuth", "Install Dev Spaces" |
| CONCEPT | Noun phrase (NOT gerund) | "Architecture overview", "Server components" |
| REFERENCE | Noun phrase | "Supported platforms", "CheCluster fields" |
| ASSEMBLY (task-based) | Imperative phrase | "Configure server components" |
| ASSEMBLY (non-procedural) | Noun phrase | "Red Hat Process Automation Manager API reference" |
An assembly is task-based if it contains procedure modules. Flag any procedure title not in imperative form, concept/reference titles using imperatives or gerunds, or task-based assembly titles using noun phrases.
Check 5b: Title length
Per the CCS peer review guide, titles should be 3-11 words long and have 50-80 characters.
| Violation | Threshold | Action |
|---|---|---|
| Too short | 1-2 words AND title is vague without context | Flag — add descriptive context |
| Too long | Over 11 words OR over 80 resolved characters | Flag — shorten by removing redundant qualifiers |
| Borderline short | 2 words but unambiguous (e.g., "Creating workspaces") | Do NOT flag — acceptable in context |
When counting characters, resolve AsciiDoc attributes to their display text (e.g., {prod-short} = "OpenShift Dev Spaces" = 20 chars).
Check 5c: Title quality
| Criterion | Rule |
|---|---|
| Descriptive | A reader should understand what the content covers from the title alone |
| Customer-focused | Focus on customer tasks, not product features |
| Sentence case | Only proper nouns, product names, and Kubernetes resource names are capitalized |
| No weak openers | Do not start concept titles with "About" or "Understanding" — use a noun phrase that directly names the concept |
| No vague titles | Single-word titles like "Architecture" or "Gateway" lack context — add the product or component name |
| Correct article before attributes | {prod-short} resolves to "OpenShift Dev Spaces" (vowel sound) — use "an {prod-short}", not "a {prod-short}" |
| No redundant product names | Do not hardcode product names before attributes that already contain them (e.g., "OpenShift {prod}" doubles "OpenShift") |
| Concise phrasing | Remove filler words ("the code of applications running in" → "application code from") |
| Score | Criteria |
|---|---|
| 4 | All files use correct prefixes, all content type declarations match, all content matches declared type, all titles follow conventions |
| 3 | 1-3 minor issues (e.g., a borderline title, a concept with a minor procedural element) |
| 2 | Multiple files with wrong prefixes, missing declarations, or content type mismatches |
| 1 | Content is not modularized or no consistent structure |
Record: total file count, count by content type, number of violations per check.
Reference: https://github.com/redhat-documentation/modular-docs/tree/main/modular-docs-manual/files
The official templates define the required structural elements for each module type. Every module must conform to its type's template.
Every module (except snippets) must have these 4 elements:
:_mod-docs-content-type: attribute as the first content line (value: CONCEPT, PROCEDURE, REFERENCE, or ASSEMBLY)[id="name_{context}"] anchor with {context} suffix= Title level-1 heading[role="_abstract"] annotation followed by a short description paragraphFor each .adoc file in the assemblies and topics directories, verify all 4 elements are present. Report any files missing any element.
Per the official procedure template, procedure modules must have:
.Procedure section followed by ordered list steps (. )The following block titles are optional but, when present, must appear in the correct order:
| Block title | Position | Required? |
|---|---|---|
.Prerequisites or .Prerequisite | Before .Procedure | Optional |
.Procedure | Required position | Required |
.Verification, .Results, or .Result | After .Procedure | Optional |
.Troubleshooting, .Troubleshooting steps, or .Troubleshooting step | After .Verification | Optional |
.Next steps or .Next step | After .Troubleshooting | Optional |
.Additional resources | Last section | Optional |
Each block title can appear at most once per module. Check all procedure files for:
.Procedure with ordered list stepsThese block titles are ONLY allowed in procedure modules:
.Prerequisites / .Prerequisite.Procedure.Verification / .Results / .Result.Troubleshooting / .Troubleshooting steps / .Troubleshooting step.Next steps / .Next stepSearch ALL concept, reference, and assembly files for these block titles. Any occurrence is a violation.
For every file that contains .Additional resources, verify that [role="_additional-resources"] appears on the line immediately before it. A missing role annotation is a violation.
Reference: https://redhat-documentation.github.io/modular-docs/#prerequisites
If a procedure includes prerequisites, verify:
Check 5a: Label format
.Prerequisites (plural, dot-prefixed AsciiDoc block title), even with a single prerequisite item.Prerequisite (singular), **Prerequisites** (bold pseudo-heading), == Prerequisites (heading)Check 5b: Formatting
* bullet markers+ continuation — not placed as standalone blocks between .Prerequisites and .ProcedureCheck 5c: Maximum count
Check 5d: No steps in prerequisites (declarative language)
Prerequisites are conditions that must already be true, not steps the user must perform.
| Pattern | Assessment |
|---|---|
| "You have access to..." | GOOD — declarative condition |
| "A running instance of..." | GOOD — declarative state |
"tool-name is installed." | GOOD — declarative condition |
| "You must have access to..." | BAD — imperative "must have", change to "You have" |
| "Install the CLI tool." | BAD — imperative action step |
| "Ensure that you have..." | BAD — imperative instruction |
| "To get X, rebuild Y." | BAD — imperative action disguised as prerequisite |
| "Ask a DNS provider to..." | BAD — imperative action step |
A prerequisite may reference another procedure with an xref for HOW to achieve the condition (e.g., "{prod-cli}. See: xref:proc_installing-the-dsc-management-tool_{context}[].").
Check 5e: Placement
.Prerequisites must appear before .Procedure.Procedure unless attached to a list item via + continuationCommon placement violations:
| Pattern | Problem | Fix |
|---|---|---|
Standalone [WARNING] block between prerequisites and .Procedure | Content gap between sections | Attach to last prerequisite item with + continuation |
include::snippets/... between prerequisites and .Procedure | Snippet renders outside list | Attach to last prerequisite item with + continuation |
[IMPORTANT] block with imperative items between prerequisites and .Procedure | Combines placement and language violations | Convert to proper prerequisite list items with declarative wording |
| Score | Criteria |
|---|---|
| 4 | All modules conform to their official template — all required elements present, correct block title usage, no procedure-only titles in wrong types, all Additional resources annotated, all prerequisites use declarative language with correct formatting |
| 3 | 1-3 minor issues (e.g., a missing optional annotation, one misplaced block title) |
| 2 | Multiple files missing required elements or widespread block title violations |
| 1 | Templates not followed or not assessed |
Record: total files checked, checks performed per file, number of violations per check category.
Reference:
P5 checks that every non-negotiable modular element is present AND meets quality standards. The structural presence of elements is checked in P4. P5 adds the quality dimension — particularly for the short description (abstract).
Reference: "Rewrite for Impact: DITA short descriptions" (CCS presentation)
Every non-snippet module must have:
:_mod-docs-content-type: attribute as first content line[id="name_{context}"] anchor with {context} suffix= Title level-1 heading[role="_abstract"] annotation followed by a prose paragraphIf P4 Check 1 passed, the above 4 elements are already verified. Additionally, verify:
Abstract formatting rules (AsciiDoc-specific):
| Rule | Check |
|---|---|
| Blank line between title and abstract | There must be at least one blank line between the = Title line and [role="_abstract"]. Other content (anchors, passthrough comments) may appear between them, but a blank line must exist. |
| No blank line between annotation and paragraph | [role="_abstract"] must be followed immediately by the abstract paragraph on the next line — no blank lines between them. A blank line after the annotation disconnects the paragraph from the abstract role, making the abstract empty in DITA. |
| Single paragraph | The abstract must be exactly one contiguous paragraph. No blank lines within it, no code blocks, no lists, no admonition blocks. A blank line must terminate the abstract before any subsequent body content. |
| Character count 50-300 | The abstract paragraph must be between 50 and 300 characters. Count raw AsciiDoc text (attributes like {prod-short} count as their literal text, e.g., 12 characters). "300 characters is between 42 and 75 words" (CCS presentation). |
Common structural violations:
| Pattern | Problem | Fix |
|---|---|---|
Blank line after [role="_abstract"] | Abstract is empty in DITA conversion | Remove the blank line |
| Abstract flows into code block | Code block becomes part of abstract (inflated character count) | Insert blank line after abstract paragraph to separate |
| Abstract flows into bullet list | List becomes part of abstract | Insert blank line after abstract paragraph |
| Multiple paragraphs before first block title | Only the first paragraph is the shortdesc; the rest is <context> in DITA | Ensure only one paragraph between [role="_abstract"] and the first blank line |
Per the DITA 1.3 specification, the short description (the paragraph after [role="_abstract"]) "represents the purpose or theme of the topic" and is "intended to be used as a link preview and for search results."
Structural requirements:
| Criterion | Rule |
|---|---|
| Word count | Max 50 words — "a single, concise paragraph containing one or two sentences of no more than 50 words" (DITA 1.3 spec) |
| Completeness | Must be complete sentences, not fragments ending in colons |
| Self-contained | Must not flow into a list or block below it; must not use "the following" to reference content below |
| Placement | Must be prose immediately after [role="_abstract"] — no admonition blocks or passthrough comments between the annotation and the paragraph |
| Link preview | Must work as a standalone snippet in search results — no context-dependent pronouns, no xrefs, no references that only make sense within the document |
Content requirements by module type:
| Module type | Short description must... |
|---|---|
| PROCEDURE | Explain WHAT the user can accomplish AND WHY (benefit/purpose). Not just "Do X." |
| CONCEPT | Answer "What is this?" AND "Why do I care about this?" |
| REFERENCE | Describe what the reference item does, what it is, or what it is used for |
| ASSEMBLY | Explain what the user will accomplish by working through the modules (the user story reworded) |
Reader motivation: The short description must describe WHY the user should read the content — what they will gain, accomplish, or understand. A reader scanning search results should immediately understand whether this content addresses their need.
SEO and AI discoverability: The short description should include keywords that users are likely to search on. For technical documentation, this means including relevant product names, technology terms, and action verbs that match user search intent.
Violations to flag:
| Category | Pattern | Example |
|---|---|---|
| Over word limit | Exceeds 50 words | Count words in the abstract paragraph; attributes like {prod-short} count as 1 word |
| Self-referential | "This topic describes...", "This section covers...", "Learn how to...", "The following steps describe..." | "The following steps describe how to create the required objects." |
| Forward-referencing | "the following methods:", "the following field descriptions", "as shown below" | "Implement the following methods:" (dangling reference in search snippet) |
| Title repetition | Restates the title with "You can" or imperative rewording and adds nothing new | Title: "Listing all workspaces" → SD: "You can list your workspaces by using the command line." |
| Missing WHY | States WHAT to do but not WHY it matters or what the user gains | "Configure the Dashboard to display custom samples." (no benefit) |
| Sentence fragment | Ends with a colon and flows into a list | "Implement the following methods:" |
| Poor link preview | Depends on title context, starts with pronouns, or is too vague to stand alone | "It is possible to fine-tune the log levels." (what log levels? which product?) |
| Fallback framing | Positions the content as secondary to another topic | "If you have trouble doing X, you can do Y instead." |
| Missing keywords | Contains no searchable technical terms relevant to the topic | Abstract with only generic words, no product/technology terms |
Verify:
[role="_abstract"] annotation is followed immediately by a prose paragraph (no admonition blocks, no passthrough comments, no blank lines with markup between them)| Score | Criteria |
|---|---|
| 4 | All modules have all required elements; all short descriptions meet DITA quality standards (correct length, explain WHAT + WHY, no self-referential language, no title repetition, complete sentences) |
| 3 | All structural elements present; fewer than 15 short descriptions have quality issues (missing WHY, title repetition, or fragments) |
| 2 | Structural elements missing in multiple files or widespread short description quality failures |
| 1 | Required elements not present or not assessed |
Record: total files, violations per category (length, self-referential, title repetition, missing WHY, fragments), severity counts (high/medium/low).
Reference:
An assembly is "the docs realization of a user story" — a collection of modules that describes how to accomplish a single user goal. Every assembly must conform to the official template AND represent a coherent user story.
For each assembly file, verify these required elements:
:_mod-docs-content-type: ASSEMBLY as first content line[id="assembly_name_{context}"] anchor with {context} suffix= Title level-1 heading[role="_abstract"] followed by an introduction paragraphinclude:: directive[leveloffset=+N] on every include:: directiveFlag any assembly missing any element. Flag any include:: missing [leveloffset=+N].
Per the modular docs guide:
For each assembly, check whether the title form matches its content. A task-based assembly with a noun-phrase title is a violation.
For each assembly, verify that every include:: path points to a file in the topics directory, NOT another file in the assemblies directory. Assembly nesting is a violation.
Each assembly should document a single, coherent user story. For each assembly:
Signs of poor user story coherence:
The introduction (abstract paragraph) should be the user story reworded. For each assembly, verify:
[role="_abstract"] annotation with no text)| Score | Criteria |
|---|---|
| 4 | All assemblies follow the template, use correct title conventions, avoid nesting, represent coherent user stories, and have action-oriented introductions |
| 3 | 1-3 minor issues (e.g., a borderline user story, one weak introduction, a known ID inconsistency) |
| 2 | Multiple assemblies missing template elements, mixing user stories, or with non-functional introductions |
| 1 | Assemblies do not follow the template or user story principle |
Record: total assemblies, per-assembly pass/fail, specific violations per check.
Reference: https://redhat-documentation.github.io/modular-docs/#modular-docs-terms-definitions
Content must not be deeply nested in the TOC. The recommended maximum is 3 levels of content nesting.
For migration assessments, start counting levels where user content starts, not including categories and the repetitive book titles that Pantheon generates. The Pantheon publishing system adds Category → Book title layers above the content — these do not count toward the 3-level limit.
| Level | What it contains | AsciiDoc mechanism |
|---|---|---|
| Level 1 | Assemblies and standalone topics included from master.adoc | include::assemblies/...adoc[leveloffset=+1] or include::topics/...adoc[leveloffset=+1] |
| Level 2 | Topics included from assemblies | include::topics/...adoc[leveloffset=+1] inside an assembly |
| Level 3 | Subsections within topics (== headings) or sub-topics at leveloffset=+2 | == Heading inside a topic, or include::topics/...adoc[leveloffset=+2] inside an assembly |
Level 4 would be a violation: === headings in topics, topics including other topics, or assemblies including assemblies.
Read each master.adoc file. Verify every include:: directive points to:
assemblies/ (an assembly)topics/ (a standalone topic)common/ file (metadata — does not count as content nesting)Flag any include pointing to an unexpected location or nesting pattern.
For every assembly file in assemblies/, read all include:: directives. Verify every include points to a file in topics/ or snippets/ — never to a file in assemblies/.
Assembly nesting creates Level 4+ content, which violates the 3-level limit.
For every topic file in topics/, search for include:: directives. Verify all includes point to files in snippets/ — never to other files in topics/.
Topic nesting creates Level 4+ content when the parent topic is already at Level 2.
Search all topic files for === headings (AsciiDoc level-3 headings). When a topic is included at Level 2 via an assembly, a === heading becomes Level 4 in the TOC — a violation.
Notes:
== headings in concept topics are acceptable (Level 3 in the TOC)==== lines used as admonition/example block delimiters are NOT headings — do not flag themleveloffset=+2 for sub-topics; verify that these sub-topics contain no == headings (which would push to Level 4)| Violation | Fix |
|---|---|
| Assembly includes assembly | Flatten: promote inner assembly's topics into the outer assembly, or make both top-level assemblies in master |
| Topic includes topic | Extract the included content into a snippet, or merge the two topics |
=== heading in topic | Restructure: use bold text, definition lists, or split into separate topics |
== heading in leveloffset=+2 sub-topic | Remove the subsection or restructure the assembly to use leveloffset=+1 |
| Score | Criteria |
|---|---|
| 4 | Strict 3-level hierarchy — 0 violations across all 4 checks |
| 3 | 1 minor nesting issue (e.g., a single === heading in one topic) |
| 2 | Assembly-inside-assembly nesting found, or multiple === headings |
| 1 | Deeply nested structure with no clear hierarchy or not assessed |
Record: total files checked per check, number of violations, specific file paths with violations.
Each file must use the modular documentation content type (CONCEPT, PROCEDURE, REFERENCE) that is most appropriate for the information it conveys. This goes beyond structural checks (P3/P4) — it verifies that the content type selection is correct.
IMPORTANT — Distinguishing automated checks from manual assessment: The check-content-types.py script performs automated structural checks (prefix vs declared type, required elements, invalid block titles, disallowed == subsections in PROCEDURE files, and non-ordered list content after .Procedure). It does NOT perform semantic classification of whether the overall file content is best modeled as CONCEPT vs PROCEDURE vs REFERENCE. The checks below (Check 1-5) are manual assessment steps that require reading and understanding the file content. When reporting results, clearly separate:
check-content-types.py (prefix mismatch, missing attributes, invalid block titles, == subsections in procedures, non-ordered list after .Procedure)Do NOT present manual assessment findings as if they came from the automated script.
Every PROCEDURE file must have a .Procedure section with ordered steps (. ) that are actionable instructions. Flag:
.Procedure contains only an xref redirect with no actual stepsCONCEPT files must explain what/why — not how to do something. Flag:
. ) that function as undeclared procedures — rewrite as prose summary or unordered list.Procedure sections (also caught by P4 Check 3)Do NOT flag:
*) — these are fine== subsections — these are allowedREFERENCE files must contain tables, definition lists, or structured lookup data. Flag files that are primarily narrative explanation (→ should be concept) or step-by-step instructions (→ should be procedure).
Each file must convey one type of information. Flag files that mix significant procedural steps with conceptual explanation in a way that should be split into separate modules.
Flag concept files that contain only an abstract and xrefs (typically ≤15 lines). These should be absorbed into the parent assembly's introductory text. Also flag orphaned concept files that are not included from any assembly.
| Score | Criteria |
|---|---|
| 4 | All content uses the correct content type, no procedural content in concepts, no trivial procedures, no orphaned files |
| 3 | 1-3 minor issues (e.g., one thin wrapper, one concept with ordered-list steps rewritten as prose) |
| 2 | Multiple content type mismatches or widespread thin wrappers |
| 1 | Content types not checked or pervasive mismatches |
Record: total files checked per type, violations per check category, files fixed. Clearly label which findings are from automated scripts and which are from manual assessment.
Content must be grammatically correct and follow American English conventions.
Use American spellings. Flag and fix British variants:
| British | American |
|---|---|
| behaviour | behavior |
| colour | color |
| customise | customize |
| analyse | analyze |
| organisation | organization |
| licence (noun) | license |
| centre | center |
| defence | defense |
| catalogue | catalog |
| programme | program |
When an AsciiDoc attribute resolves to a word starting with a vowel sound, the preceding article must be "an", not "a". Check all prose (not code blocks or YAML) for these patterns:
| Attribute | Resolves to | Starts with | Correct article |
|---|---|---|---|
{prod-short} | OpenShift Dev Spaces | vowel "O" | an {prod-short} |
{orch-name} | OpenShift | vowel "O" | an {orch-name} |
{ocp} | OpenShift Container Platform | vowel "O" | an {ocp} |
{prod} | Red Hat OpenShift Dev Spaces | consonant "R" | a {prod} |
{devworkspace} | Dev Workspace | consonant "D" | a {devworkspace} |
Important: When an adjective intervenes between the article and the attribute, the article agrees with the adjective, not the attribute. For example, "a new {orch-name} Secret" is correct because "a" modifies "new" (consonant).
Search patterns:
" a {prod-short}" — all matches are violations" a {orch-name}" — violations unless an adjective follows (e.g., "a new {orch-name}")" a {ocp}" — all matches are violationsVerify that singular subjects take singular verbs and plural subjects take plural verbs. Common issues in technical docs:
| Pattern | Problem | Fix |
|---|---|---|
| "content are empty" | "content" (uncountable) takes singular verb | "contents are empty" or "content is empty" |
| "a ... containers" | article "a" with plural noun | Remove article or use singular noun |
| "data are" | Red Hat style: "data" is singular | "data is" |
Hyphenate compound modifiers that precede a noun:
| Pattern | Problem | Fix |
|---|---|---|
| "{prod-short} managed containers" | unhyphenated compound modifier | "{prod-short}-managed containers" |
| "command line tool" | unhyphenated compound modifier | "command-line tool" |
Do NOT hyphenate when the modifier follows the noun: "the containers are {prod-short} managed" (no hyphen needed).
| Score | Criteria |
|---|---|
| 4 | All content uses American English spelling, correct article usage before attributes, correct subject-verb agreement, and proper hyphenation |
| 3 | 1-3 minor issues (e.g., a few article mismatches, one British spelling) |
| 2 | Multiple British spellings, widespread article errors, or subject-verb disagreements |
| 1 | Content not checked or pervasive grammar issues |
Record: total files checked, violations per check category, files fixed.
After fixing any violations, re-run all checks to confirm compliance. Run Vale to ensure no new warnings were introduced:
cd "$DOCS_REPO"
vale assemblies/ topics/ titles/administration_guide/master.adoc titles/user_guide/master.adoc