Human-Readable IDs (HRIDs)
Human-Readable IDs (HRIDs) are short, memorable identifiers like USR-001 or COMPONENT-SYS-042. They make requirements easy to reference in conversations, code comments, and documentation.
HRID Format
The general format is:
{NAMESPACE*}-{KIND}-{ID}
Where:
NAMESPACE*= Zero or more namespace segments (optional)KIND= Requirement type/categoryID= Numeric identifier
Components
Namespace (Optional)
Zero or more segments separated by hyphens:
USR-001 # No namespace
COMPONENT-USR-001 # One namespace level
AUTH-LOGIN-SYS-042 # Two namespace levels
PRODUCT-FEATURE-MODULE-SWR-123 # Three namespace levels
Purpose: Organize requirements in large projects or multi-component systems.
Rules:
- Each segment must be non-empty
- Segments are case-sensitive (by convention, use UPPERCASE)
- No special characters (letters, numbers, underscores OK)
Kind (Required)
The requirement category or type:
USR # User requirements
SYS # System requirements
SWR # Software requirements
HWR # Hardware requirements
TST # Test requirements
Purpose: Distinguish requirement levels in the hierarchy.
Rules:
- Must be non-empty
- Case-sensitive (by convention, use UPPERCASE)
- No special characters
Common conventions:
USR- User requirements (what users need)SYS- System requirements (technical specifications)SWR- Software requirements (software-specific details)HWR- Hardware requirements (hardware-specific details)TST- Test requirements (test cases)
You're free to use any KIND values that make sense for your project.
ID (Required)
A positive integer:
USR-1 # Valid
USR-001 # Valid (zero-padded)
USR-42 # Valid
USR-1000 # Valid
Purpose: Unique number within the KIND (or NAMESPACE-KIND combination).
Rules:
- Must be a positive integer (1, 2, 3, ...)
- Zero is not allowed
- Negative numbers are not allowed
Display format: IDs are zero-padded to a configurable width (default 3 digits):
USR-001 # 3 digits (default)
USR-042
USR-123
USR-1000 # Exceeds padding, shows all digits
Configure padding in config.toml:
digits = 3 # USR-001
# or
digits = 4 # USR-0001
Parsing Examples
Valid HRIDs
USR-001 # Simple: KIND-ID
SYS-042 # Different kind
USR-1 # No leading zeros
USR-1000 # Large ID
COMPONENT-USR-001 # One namespace
AUTH-LOGIN-SYS-042 # Two namespaces
A-B-C-D-E-KIND-123 # Five namespaces
Invalid HRIDs
USR001 # Missing hyphen
-USR-001 # Leading hyphen
USR-001- # Trailing hyphen
USR--001 # Double hyphen
USR- # Missing ID
-001 # Missing KIND
USR-abc # Non-numeric ID
USR-0 # Zero ID not allowed
USR--001 # Empty segment
Namespaces in Practice
When to Use Namespaces
Large projects: Organize by subsystem
AUTH-USR-001 # Authentication subsystem user requirements
AUTH-SYS-001
PAYMENT-USR-001 # Payment subsystem user requirements
PAYMENT-SYS-001
Product families: Distinguish shared vs. product-specific
CORE-SYS-001 # Shared by all products
MOBILE-USR-001 # Mobile app specific
WEB-USR-001 # Web app specific
Organizational structure: Match company divisions
FRONTEND-DASHBOARD-USR-001
FRONTEND-REPORTS-USR-001
BACKEND-API-SYS-001
BACKEND-DATABASE-SYS-001
When Not to Use Namespaces
Small projects: Added complexity without benefit
# Overkill for a small project
TODO-APP-CORE-STORAGE-SYS-001
# Better
SYS-001
Flat hierarchy: If you don't need organizational structure
USR-001, USR-002, SYS-001, SYS-002
Use namespaces only when they add clarity, not as a default.
HRID Assignment
Auto-Incrementing
req add automatically assigns the next available ID:
req add USR # Creates USR-001
req add USR # Creates USR-002
req add SYS # Creates SYS-001
req add USR # Creates USR-003
The next ID is determined by examining existing requirements and incrementing the highest ID found.
With Namespaces
Specify the namespace in the KIND argument:
req add AUTH-USR # Creates AUTH-USR-001
req add AUTH-SYS # Creates AUTH-SYS-001
req add PAYMENT-USR # Creates PAYMENT-USR-001
req add AUTH-USR # Creates AUTH-USR-002
Each NAMESPACE-KIND combination has its own sequence.
Gaps in Numbering
If you delete USR-002, creating a gap:
USR-001.md # Exists
# USR-002.md deleted
USR-003.md # Exists
The next req add USR creates USR-004, not USR-002. Requiem always uses the next number after the highest existing ID.
Rationale: Reusing deleted IDs could confuse people referring to old documentation or Git history that mentioned USR-002.
HRID Best Practices
Use Consistent Naming
Pick a convention and stick to it:
# Good (consistent)
USR-001, USR-002, SYS-001, SYS-002
# Bad (inconsistent)
USR-001, User-002, SYS-001, system-002
Keep KINDs Short
# Good
USR, SYS, SWR, TST
# Less good (too verbose)
USER_REQUIREMENTS, SYSTEM_REQUIREMENTS
Short KINDs are easier to type and read.
Use UPPERCASE
# Good
USR-001
# Works but unconventional
usr-001
Usr-001
UPPERCASE is the standard convention in requirements engineering.
Document Your KIND Meanings
Create a glossary:
# Requirements Glossary
- **USR**: User requirements (stakeholder needs)
- **SYS**: System requirements (technical specifications)
- **SWR**: Software requirements (implementation details)
- **TST**: Test requirements (test cases)
HRID Stability
HRIDs Can Change
Unlike UUIDs, HRIDs are not guaranteed stable. They might change if:
- Requirements are renumbered
- Namespaces are reorganized
- Projects are merged
Correcting HRIDs
If you manually rename a requirement file, run:
req clean
This updates parent hrid fields to reflect the new names, while UUIDs keep links valid.
Example:
# Manually rename
mv USR-001.md AUTH-USR-001.md
# Update parent references
req clean
# Children that referenced USR-001 now show AUTH-USR-001
Referencing Requirements
In documentation and code, always reference by HRID for readability:
#![allow(unused)] fn main() { // Satisfies USR-042: Email validation fn validate_email(email: &str) -> Result<(), ValidationError> { // ... } }
But remember that HRIDs might change. For machine processing, use UUIDs.
Namespace Configuration
Configure allowed namespaces and kinds in config.toml:
_version = "1"
# Optional: Restrict allowed kinds
allowed_kinds = ["USR", "SYS", "SWR", "TST"]
# Optional: Set ID padding
digits = 3
Note: Namespace validation is not yet implemented. You can use any namespace structure. Future versions may allow restricting namespaces.
HRID Storage Location
Important: HRIDs are stored in two places:
- Filename:
USR-001.md,COMPONENT-SYS-042.md - First Heading:
# USR-001 Title,# COMPONENT-SYS-042 Title
The HRID must appear as the first token in the first markdown heading:
---
_version: '1'
uuid: ...
---
# USR-001 Plain Text Storage
Requirements are stored as plain-text files...
Not in frontmatter: The HRID is NOT stored in the YAML frontmatter. This change was made to improve compatibility with Sphinx and MdBook.
Filename Matching
Requirement filenames must match the HRID in the first heading:
USR-001.md with heading: # USR-001 Title → Valid
COMPONENT-SYS-042.md with: # COMPONENT-SYS-042 → Valid
Mismatches cause errors:
USR-001.md with heading: # USR-002 Title → Error!
The HRID in the filename is authoritative. Requiem derives the HRID from the filename and expects the heading to match.
Next Steps
Now that you understand HRIDs, learn how to create requirements with req add.