Picked: ClaudeRule (FileType::ClaudeRule, validator ClaudeRulesValidator, schema ClaudeRuleSchema)
Why:
- Same tool family (Claude Code), same path pattern (.claude//*.md)
- Only 2 rules (CC-MEM-011, CC-MEM-012) - simplest possible CC-family validator
- Self-contained YAML frontmatter schema using serde_yaml + heuristic unknown-key detection
- Valid and invalid fixtures exist under tests/fixtures/valid/claude-rules/ and invalid/claude-rules/
- No extra crate dependencies beyond serde_yaml
- types.rs - add ClaudeOutputStyle variant after ClaudeRule (line 42)
- detection.rs - add output-styles arm after ClaudeRule arm (lines 381-386)
- schemas/output_style.rs - new file, mirror claude_rules.rs
- schemas/mod.rs - add pub mod output_style at line 33
- rules/output_style.rs - new file, mirror claude_rules.rs
- rules/mod.rs - add pub mod output_style at line 32
- registry.rs - EXPECTED_BUILTIN_COUNT 73->74, new factory fn, ClaudeProvider entry, test array 42->43
- knowledge-base/rules.json - increment total_rules, add N CC-OS entries
- crates/agnix-rules/rules.json - cp from knowledge-base/rules.json
- knowledge-base/VALIDATION-RULES.md - new section, footer count
- tests/fixtures/ - valid and invalid output-style fixtures
- output_style.rs tests - co-located #[cfg(test)] mod tests
- config/rule_filter.rs: add CC-OS- branch to is_category_enabled()
- config.rs: add output_styles: bool to RuleConfig
- rule_parity.rs: add CC-OS- to valid_prefixes, claude-output-styles to valid_categories, fixture mapping
CC-OS- prefix: Zero existing rules, no collision confirmed. FileType::ClaudeOutputStyle: Matches convention (ClaudeRule, ClaudeMd). OutputStyleSchema: Consistent with ClaudeRuleSchema. OutputStyleValidator: Consistent with ClaudeRulesValidator.
-
EXPECTED_BUILTIN_COUNT sentinel (registry.rs line 401): +1 per validator entry. 73->74. Test array [FileType; 42] -> [FileType; 43].
-
Exhaustive match arrays in types.rs tests: three functions list every FileType variant in typed arrays; all must include ClaudeOutputStyle or compile fails.
-
rule_parity.rs valid_prefixes (line 167): CC-OS- must be listed or test_all_rules_implemented fails.
-
rule_parity.rs valid_categories (line 509): test_rules_json_integrity panics on unknown category; add claude-output-styles.
-
rule_parity.rs infer_fixture_coverage (line 280): test_fixture_coverage_exists fails without claude-output-styles -> directory mapping.
-
i18n locale files: Avoid rust_i18n::t!() for CC-OS rules; use inline strings to skip editing en.yml, es.yml, zh-CN.yml.
-
Hyphenated YAML key keep-coding-instructions: Cannot use #[serde(rename)] with hyphens. Extract manually from serde_yaml::Mapping as done for paths in claude_rules.rs.
-
VALIDATION-RULES.md anchor: Parity test looks for (lowercase ID).
-
Autofix footer count: stays at 126 if no CC-OS rules have autofix:true.
-
Clippy Rust 1.95 -D warnings (CI stricter than local 1.92): avoid unnecessary_sort_by (use .sort()), needless_borrows_for_generic_args, unnecessary_literal_unwrap (use .expect()), gate unix-only imports with #[cfg(unix)].
-
total_rules in rules.json: test_rules_json_integrity asserts total_rules == rules.len(); always sync.
-
test_sum_of_category_providers_equals_expected (registry.rs line 1947): Must match EXPECTED_BUILTIN_COUNT; ClaudeProvider entry and constant must change together.
-
Safe execution order: schema -> validator -> file_types -> registry -> config.rs -> rule_filter.rs -> rules.json (both copies) -> VALIDATION-RULES.md -> fixtures -> rule_parity.rs. Run cargo test --workspace before adding fixtures.
| ID | Name | Severity | Normative | Checks | Bad example |
|---|---|---|---|---|---|
| CC-OS-001 | Missing Output Style Description | LOW | SHOULD | description absent or empty; needed for /config picker label | name without description in frontmatter |
| CC-OS-002 | Invalid keep-coding-instructions Type | HIGH | MUST | keep-coding-instructions present but not YAML boolean; e.g. string yes, number 1, null | keep-coding-instructions: yes (quoted string) |
| CC-OS-003 | Unknown Output Style Frontmatter Key | MEDIUM | SHOULD | Top-level key not in {name, description, keep-coding-instructions}; signals typo or wrong file type | paths: - src/** (a rules field, not output-style) |
| CC-OS-004 | Empty Output Style Body | MEDIUM | SHOULD | Body after closing --- (or entire file if no frontmatter) is blank/whitespace-only; dead config | frontmatter with blank body |
| CC-OS-005 | Output Style Name Too Long | LOW | SHOULD | name value exceeds 64 chars; truncates in /config picker UI | name: this-is-a-very-long-style-name-exceeding-64-chars |
Omissions: name format constraints not documented; name not required (defaults to filename); CC-OS-006 (name+filename) over-specified for optional field.