Best Practices for Organizing Rules¶
See also: Organizing Katas
Understanding the Foundation¶
Before diving into best practices, it's crucial to understand how scopes and categories work together:
-
Categories form a universal namespace: A category like
development.coding.python.testinghas the same meaning across all scopes. Categories are NOT scope-specific. -
Multiple scopes can contain rules for the same category: For example,
python-general,team-backend, andproject-apimight all have rules fordevelopment.coding.python.testing. -
Scopes are organizational contexts: They group related categories and rules for specific purposes (company-wide standards, team conventions, project-specific requirements).
-
Scope inheritance merges rules: When you request rules from a scope with parents, you get merged results for each category across the inheritance chain.
This universal category namespace ensures consistency: when different scopes add rules to development.security, they're all contributing to the same logical category.
Part I: Organizational Foundations¶
1. Understanding Universal vs Conditional Categories¶
Universal categories - Always apply when their domain is relevant:
development.coding.quality → Always applies when writing code
development.coding.python → Always applies when writing Python
general → Always applies
Conditional categories - Only apply when explicitly chosen or context matches:
development.architecture_patterns.clean_architecture → ONLY when pattern chosen
development.coding.testing → ONLY when writing tests
development.lifecycle.review → ONLY during review phase
Rule: Clearly separate universal from conditional in your hierarchy. Don't mix them at the same level.
Anti-pattern:
development.coding
├── architecture (universal - SOLID, DRY)
└── clean_architecture (conditional - specific pattern)
Better:
development.coding
└── architecture (universal - SOLID, DRY)
development.architecture_patterns
└── clean_architecture (conditional - specific pattern)
2. Designing Hierarchical Structures¶
Use Aggregator Categories with "Do Not Use Directly" Warnings
Purpose: Provide logical grouping without forcing over-fetching
development.coding [DO NOT USE DIRECTLY; pick relevant subcategories]
├── core (universal code rules)
├── python (language-specific)
├── security (security rules)
└── testing (conditional - when writing tests)
Benefit: Users can:
- Fetch
development.coding.python(specific) - Skip
development.coding.testing(conditional) - Avoid accidentally fetching everything under
development.coding
Hierarchical Inclusion is Automatic
Remember: Fetching a parent includes ALL children.
Implication:
- Place conditional categories as siblings, not children of universal categories
- If a parent has mixed universal/conditional children, users can't selectively exclude
Example problem:
development.coding.python (universal for Python)
├── implementation (universal)
├── quality (universal)
└── testing (conditional - ONLY when writing tests)
Fetching development.coding.python forces inclusion of testing rules even when not writing tests.
Solutions:
- Document clearly that testing is conditionally included
- Move testing to sibling:
development.coding.python_testing - Support exclusion in API:
exclude=["development.coding.python.testing"]
3. Splitting and Merging Categories¶
When to Split
Split categories when:
- Different applicability conditions
development.coding.python.implementation (always for Python)
development.coding.python.testing (only when writing tests)
- Different granularity needed
development.coding.security.design (architectural patterns)
development.coding.security.implementation (coding practices)
- Rules serve different phases/activities
- Domain-specific rules exist
development.domain_specific.web_applications
development.domain_specific.apis
development.domain_specific.cli_tools
Don't Split When:
- Rules always apply together - Keep them in one category
- Only 1-2 rules exist - Too granular; merge into parent
- Split creates ambiguity - Which category gets which rule?
When to Merge
Merge categories when:
- Always fetched together
# Before: Always fetch both
development.coding.core
development.coding.standards
# After: Merged
development.coding.core
- Redundant scoping
# Before: Confusing split
security (top-level universal)
development.coding.security.global (also universal?)
# After: Clarify relationship or merge
development.security.core (all universal security)
├── mindset (high-level principles)
└── implementation (coding practices)
- Single rule in category
# Before: Wasteful
development.architecture_patterns.core
→ Rule: "Prefer well-known patterns"
# After: Move to parent or merge
development.architecture_patterns
→ Description includes this guidance
4. Naming Conventions¶
Use Descriptive, Unambiguous Names
Avoid:
global- ambiguous; useuniversal(applies across all scopes) orcore(base rules for this domain) insteadcommon- vaguemisc- catch-all anti-pattern
Prefer:
core- base rules for this category domainuniversal- applies across all scopes when this domain is relevantimplementation- during active codingdesign- architectural level
Use "Aggregated" in Descriptions for Parent Categories
development.coding.python
Description: "Aggregated rules that apply when the task involves Python programming"
Signals that this is a logical grouping with subdivisions.
Part II: Writing Effective Content¶
5. Writing Clear Descriptions¶
Format: "[Applicability] [What it contains]"
Universal category:
Conditional category:
development.coding.testing
Description: "Rules for writing and structuring tests. Apply when creating test code"
Conditional pattern (emphasize):
development.architecture_patterns.clean_architecture
Description: "Clean architecture rules. **ONLY apply when implementing clean architecture pattern**"
Use Bold for Critical Conditions
Make conditions unmissable:
- "ONLY apply when..."
- "DO NOT use directly; always pick the relevant subcategories"
- "Security must be enforced"
Be Explicit About Timing/Context
Good:
- "Apply when writing Python tests"
- "During active code development"
- "When designing system architecture"
- "For all code handling user input"
Bad:
- "For testing" (writing tests or running tests?)
- "Python rules" (all Python contexts or specific ones?)
- "Architecture" (designing it or following a pattern?)
Common Ambiguity Sources
Avoid these patterns:
-
"Rules related to X" - Too vague
- Better: "Rules for writing X" or "Rules applied when X"
-
"When appropriate" - Who decides?
- Better: "When {specific condition}" or "Unless explicitly excluded"
-
"General" or "Common" - General within what scope?
- Better: "Universal" or "Core" with explicit scope
-
Passive voice - "Rules that are applied..."
- Better: "Apply these rules when..."
Test Your Descriptions
Ask: "Can someone reading this description know EXACTLY when to include this category?"
# Ambiguous
development.coding.testing
Description: "Testing rules"
# Clear
development.coding.testing
Description: "Rules for writing and structuring tests. Apply when creating test code (test_*.py, *_test.py files)"
6. Writing Actionable Rules¶
Use MUST/SHOULD Consistently
MUST - Non-negotiable requirements (use commandments):
- MUST: No code comments in generated code
- MUST: Security by default
- MUST: Follow SOLID principles
SHOULD - Strong recommendations (use suggestions):
Make Rules Actionable
# Bad (not actionable)
- SHOULD: Write good tests
- MUST: Be secure
# Good (actionable)
- SHOULD: Use pytest.mark.parametrize for tests with multiple input scenarios
- MUST: Validate and sanitize all user inputs before processing
One Concern Per Rule
# Bad (multiple concerns)
- MUST: Use type hints and validate them with mypy, and also use ruff for linting
# Good (separated)
- SHOULD: Use statically-typed code
- SHOULD: Use mypy to validate typing
- SHOULD: Use ruff for linting
Part III: Common Organizational Patterns¶
7. Security Categories¶
Security Deserves Multiple Locations
Pattern:
security (top-level category)
→ "Universal security mindset. ALWAYS applies across all scopes"
→ High-level: Security is first-class citizen
development.coding.security
├── core: "Universal security requirements for code"
├── design: "Security architecture patterns"
└── implementation: "Secure coding practices"
Why both?
- Top-level
securitycategory: Ensures security is NEVER forgotten (always included) development.coding.securitycategory: Specific implementation requirements
Security Should Be
- Mandatory (MUST, not SHOULD)
- Explicit in descriptions ("Critical for web applications, APIs...")
- Subdivided by concern (design vs implementation)
- Referenced in domain-specific categories (web apps mention OWASP, CORS, etc.)
8. Language-Specific Organization¶
Pattern: coding.{language}.{aspect}
development.coding.python
├── implementation (tooling, structure, conventions)
├── quality (linting, type checking)
└── testing (test framework practices)
development.coding.javascript
├── implementation (npm, ESLint, project structure)
├── quality (TypeScript, strict mode)
└── testing (Jest patterns)
Benefits:
- Consistent across languages
- Easy to add new languages
- Clear aspect separation
Alternative (if many languages):
Part IV: Scope-Level Design¶
9. Designing Scopes¶
When to Create Separate Scopes
Create separate scopes when:
- Different teams/projects with distinct rule sets
- Different enforcement levels
company-wide (scope) → mandatory for everyone
team-backend (scope) → specific to backend team
project-xyz (scope) → overrides for specific project
- Different domains with non-overlapping rules
development (scope) → coding rules
operations (scope) → deployment, monitoring
documentation (scope) → writing docs
Scope Composition and Inheritance
Design scopes to be composable:
Query: get_rules(scopes=["company-wide", "development", "python-web"])
Result: Merged rules from all three scopes
This allows:
- Company-wide universal policies
- Development-specific coding standards
- Project-specific overrides
Part V: Quality Assurance¶
10. Anti-Patterns to Avoid¶
Catch-All Categories
Sign of poor organization.
Deeply Nested Hierarchies (>4 levels)
Too granular; hard to navigate.
Duplicated Rules
Same rule in multiple categories without clear reason.
Circular Dependencies
Category A includes rules about when to use Category B.
Implementation Details in Descriptions
Keep descriptions user-focused.
11. Maintenance Guidelines¶
Regular Audits
- Check for orphaned rules - Rules that don't fit their category
- Verify applicability - Do descriptions still match rule content?
- Remove dead rules - Deprecated tools, outdated practices
- Consolidate sparse categories - <3 rules might belong elsewhere
Versioning Strategy
Consider versioning for rule changes:
Or use scope versioning:
12. Quick Reference Checklist¶
When creating scopes/categories/rules, verify:
- [ ] Applicability is crystal clear - No guessing when to include
- [ ] Universal and conditional are separated - Different hierarchy levels
- [ ] Names are descriptive and unambiguous - No "global", "misc", "common"
- [ ] Descriptions state WHEN to apply - "Apply when..." or "ONLY when..."
- [ ] Security is mandatory and explicit - MUST rules, multiple locations
- [ ] Hierarchies are logical - Max 3-4 levels deep
- [ ] Parent categories have warnings - "DO NOT USE DIRECTLY" where needed
- [ ] Rules are actionable - Specific, measurable, implementable
- [ ] MUST vs SHOULD is consistent - Clear distinction
- [ ] One concern per rule - No compound requirements
- [ ] No catch-all categories - Everything has a proper home
- [ ] Language-specific rules follow consistent pattern - Same structure for each language
For kata-specific checklist, see Organizing Katas