Map Requirement
DevOps & Securitymap-requirementMap Requirement is an Agent Skill for devops & security published in the ComplianceAsCode/content repository on GitHub: a SKILL.md instruction file an AI agent can load to do this task.
Map rules to a single control file requirement using cross-framework analysis and rule search.
How to use this skill
Bring this guide into your coding agent with a prompt tailored to the tool you use.
- Open your project in Codex.
- Copy and paste the prompt below.
- Review files and risks before approving any action.
Inspect the Agent Skill at https://github.com/ComplianceAsCode/content/blob/HEAD/.claude/skills/map-requirement/SKILL.md and all supporting files. Report provenance, permissions, scripts, dependencies, and security risks. Propose an exact installation into .agents/skills/map-requirement, but wait for my approval before writing files or running scripts.
Copying this prompt does not install or run the skill. Review third-party files before use.
Map Requirement
Map rules to a single requirement in a control file. This is the atomic unit of the mapping workflow — it finds candidate rules, presents them to the author, and writes the selection back to the control file.
Tool Strategy
This skill uses mcp__content-agent__* tools when available (preferred — deterministic, structured results). When the MCP server is not configured, fall back to filesystem-based alternatives noted as Fallback in each step. See .claude/skills/shared/mcp_fallbacks.md for detailed fallback procedures. The skill must complete successfully either way.
Without MCP server: Cross-framework similarity search is unavailable. Candidate rules will be found by keyword search only, which may miss semantically similar but differently-worded requirements.
Arguments: $ARGUMENTS — format: <control_id> <requirement_id> --product <product_id> [--policy <path>]
Examples:
/map-requirement anssi R3 --product rhel9/map-requirement srg_gpos SRG-OS-000001-GPOS-00001 --product rhel10/map-requirement hipaa 164.312(a)(1) --product rhel9/map-requirement anssi R34 --product rhel9 --policy security_policies/anssi_2.md
Phase 1: Parse and Validate
-
Parse arguments: Extract
control_id,requirement_id,--productflag, and optional--policyflag from$ARGUMENTS. -
If no
--productspecified, discover available products and ask the user viaAskUserQuestion:- Run
ls products/(or callmcp__content-agent__list_products) to get the list of available products - "Which product are you mapping rules for?"
- Options: present the most common products from the discovered list + Other
- Run
-
Check build artifacts: Call
mcp__content-agent__list_built_products.- If the target product is NOT in the built list, ask the user via
AskUserQuestion:- "Product '{product}' has not been built yet. Rule search works best with build artifacts (expanded Jinja templates). Build it now?"
- Options:
- "Yes, build now (Recommended)" — description: "Runs
/build-product {product} --datastream-onlybefore starting the mapping session" - "No, continue without build" — description: "Rule search will use raw source files, which may miss some rules due to Jinja template parsing errors"
- "Yes, build now (Recommended)" — description: "Runs
- If user chooses to build, invoke the
build-productskill:Skill(skill="build-product", args="{product} --datastream-only"). Wait for the build to complete before continuing. - Fallback: Check if
build/{product}/rules/directory exists. If not, offer the build prompt above.
- If the target product is NOT in the built list, ask the user via
-
Load the requirement: Call
mcp__content-agent__get_control_detailswithcontrol_id.- If control not found, call
mcp__content-agent__list_controlsand show options. - Find the requirement matching
requirement_idin the controls list. - If requirement not found, list available requirement IDs and ask user to pick.
- Fallback: Read the control YAML directly from
controls/<control_id>.ymlorproducts/<product>/controls/<control_id>.yml. If the file hascontrols_dir:, read individual requirement files from that directory. To list controls, runls controls/*.ymlandls products/*/controls/*.yml.
- If control not found, call
-
Display the requirement:
## Requirement: {requirement_id} **Title**: {title} **Description**: {description} **Current status**: {status} **Current rules**: {rules or "none"} -
If no
--policyspecified, show a tip:Tip: Pass
--policy <path>to enrich mapping with the original security policy text (PDF, Markdown, HTML). This improves cross-framework matching accuracy.
Phase 1.5: Policy Enrichment (if --policy provided)
If --policy was specified:
-
Infer document type from the file extension:
.md→markdown.pdf→pdf.html→html- Otherwise →
text
-
Call
mcp__content-agent__parse_policy_documentwith:source: the policy pathdocument_type: inferred from extensionrequirement_id: the requirement ID from Phase 1- Fallback: For markdown/text files, read the file directly and search for the requirement ID. For PDF files, inform the user that PDF parsing requires the MCP server.
-
If sections returned, display the policy context:
### Policy Context (from {policy_path}) **{section_title}** {section_content} {subsection contents...} -
Store the combined section text as
policy_textfor use in Phase 2.
Phase 2: Find Candidate Rules
Execute steps 2a-2c to build a candidate list from multiple sources.
Step 2a: Cross-Framework Search
Call mcp__content-agent__find_similar_requirements with:
requirement_text: ifpolicy_textis available, use it; otherwise use the requirement's title + " " + descriptionexclude_control_id: current control_idmax_results: 10
Fallback: Extract 3-5 key terms from the requirement text. Use Grep to search for each term across controls/*.yml and products/*/controls/*.yml. Requirements matching multiple terms are likely similar. Read matched requirements to extract their rules: lists.
If results found, present them grouped by control framework:
### Similar Requirements in Other Frameworks
- [{control_id}] {requirement_id}: "{title}" → rules: {rules}
- [{control_id}] {requirement_id}: "{title}" → rules: {rules}
Extract the union of all rules from similar requirements as "cross-framework candidates".
Step 2b: Rule Search in Build Artifacts
Search for candidate rules using rendered build artifacts (Jinja-expanded, product-specific):
-
Extract 3-5 key terms from the requirement title and description.
-
For each key term, call
mcp__content-agent__search_rendered_contentwith:query: the key termproduct: the target product from Phase 1limit: 15- Fallback: If the product is not built, use
Grepto search for key terms inrule.ymlfiles underlinux_os/guide/andapplications/. This may miss rules with Jinja-templated descriptions.
-
Deduplicate results across all term searches. Combine with cross-framework candidates from Step 2a.
-
For each candidate rule, use
mcp__content-agent__get_rendered_rule(orget_rule_details) to read its title and description. Reason about which rules best match the requirement:- Look for rules whose title/description semantically matches the requirement
- Prioritize rules that also appeared in Step 2a cross-framework results
- Consider rule severity alignment with the requirement's intent
- Rank candidates by relevance
-
Present the top candidates in a table:
### Rule Candidates | Rule ID | Title | Source | Reasoning | |---------|-------|--------|-----------| | {rule_id} | {title} | cross-ref / search | {why it matches} |
Step 2c: Product Availability Check
Since search_rendered_content only returns rules present in the target product's build, all search results are already confirmed available. For cross-framework candidates (from Step 2a) that did NOT appear in the rendered search, call mcp__content-agent__get_rule_product_availability to verify availability.
Fallback: For each rule, find its rule.yml and check the identifiers: section for cce@<product> entries. Also grep for the rule ID in products/<target_product>/profiles/*.profile and products/<target_product>/controls/*.yml.
Flag rules that are NOT available for the target product:
Warning: Rule '{rule_id}' has identifiers for {other_products} but NOT for {target_product}.
May need platform/identifier additions to work for {target_product}.
For rules missing from the target product, use LLM judgment to assess portability:
- If the rule uses a template (
templateis not None in get_rule_details), it's likely portable - If it has platform constraints mentioning specific products, note the constraint
- Optionally call
mcp__content-agent__get_rule_detailswithrendered_detail=fullandproduct=<a product that has it>to read the actual OVAL/remediation and assess whether it's product-specific
Phase 3: Author Decision
-
Build unified candidate list: Combine cross-framework and search candidates, deduplicated by rule_id, sorted by relevance.
-
Present candidates using
AskUserQuestionwithmultiSelect: true:- "Select rules to map to requirement '{requirement_id}: {title}'"
- Options: top candidates (up to 4, the AskUserQuestion limit), each with description showing source (cross-framework, search, or both) and reasoning
- If more than 4 candidates, present top 3 + "Show more candidates"
-
Ask about status using a separate
AskUserQuestion:- "How should this requirement be marked?"
- Options:
- "Automated" — rules fully cover the requirement
- "Partially automated" — rules cover some aspects
- "Not applicable" — requirement doesn't apply to this product
- "Skip for now" — don't change anything
Phase 4: Write Selection
Based on author's decision:
If rules were selected (automated or partially_automated):
-
Call
mcp__content-agent__update_requirement_ruleswith:control_id: the control file IDrequirement_id: the requirement IDrules: the selected rule IDsstatus: "automated" or "partially_automated" based on author's choice- Fallback: Find the requirement file using
get_requirement_file_pathfallback (see above). UseEdittool to update therules:andstatus:fields in the YAML. Be careful to preserve existing formatting, comments, and Jinja2 templating.
-
Verify the result:
- Check
successfield in the response - If failed, report the error and suggest manual editing
- Check
-
Report:
Updated requirement '{requirement_id}' in '{control_id}': - Rules: {rules} - Status: {status} - File: {file_path}
If marked not applicable:
-
Call
mcp__content-agent__update_requirement_ruleswith:control_id: the control file IDrequirement_id: the requirement IDrules: [] (empty list)status: "not_applicable"- Fallback: Edit the requirement YAML directly to set
status: not_applicableandrules: [].
-
Report the change.
If skipped:
Report that no changes were made and move on.
Phase 5: Summary
Present a brief summary:
## Mapping Complete
Requirement: {requirement_id} ({title})
Control file: {control_id}
Action: {mapped N rules / marked not applicable / skipped}
File modified: {file_path or "none"}
Next steps:
- Map another requirement: `/map-requirement {control_id} <next_req_id> --product {product}`
- Map all unmapped: `/map-controls {control_id} --product {product}`
- Review changes: `git diff controls/`
Error Handling
- If
update_requirement_rulesfails, display the error message and suggest the user manually edit the file. Usemcp__content-agent__get_requirement_file_pathto find the correct file, or Fallback: locate it by reading the control YAML'scontrols_dir:field or searching for the requirement in the inlinecontrols:list. - If rule search returns no results, rely only on cross-framework candidates from step 2a.
- If no candidates are found from any source, inform the user and offer options: "Skip", "Enter rule IDs manually", "Create new rule (use /create-rule)".