Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Welcome to Requiem, a modern plain-text requirements management tool designed for software and systems engineers who value simplicity, speed, and integration with their existing workflows.

What is Requiem?

Requiem (package name: requirements-manager, CLI: req) is a spiritual successor to Doorstop, reimagined for the modern development landscape. It enables teams to:

  • Manage requirements as plain text - Store requirements as markdown files with YAML frontmatter, making them human-readable, version-controllable, and diff-friendly
  • Build traceable requirement hierarchies - Link requirements together to form directed acyclic graphs (DAGs) that trace from high-level user needs down to detailed specifications
  • Support multiple parents - Unlike many tools, Requiem allows a single requirement to satisfy multiple parent requirements, reflecting real-world complexity
  • Integrate seamlessly - Works alongside documentation tools like Sphinx and MdBook, fitting naturally into your existing documentation workflow
  • Scale with performance - Built in Rust with parallel processing, Requiem is designed to be much, much faster than its predecessors

When to Use Requirements Management

Requirements management is essential when:

  • Traceability is critical - Regulated industries (aerospace, medical devices, automotive) often require proof that each requirement is implemented and tested
  • Teams need alignment - Multiple stakeholders (users, developers, testers, managers) need a shared understanding of what's being built
  • Systems are complex - Large projects with many interconnected components benefit from formal requirement tracking
  • Change management matters - Understanding the impact of requirement changes across dependent systems is crucial
  • Documentation must be maintained - Requirements serve as the foundation for design documents, test plans, and user manuals

Project Status

Requiem is in early development and not yet ready for production use. Current status:

Implemented:

  • ✅ Manage requirements, specifications, and documents in plain text
  • ✅ Create and link requirements with human-readable IDs
  • ✅ Support multiple parent relationships
  • ✅ Content fingerprinting for change detection
  • ✅ Integration with MdBook and Sphinx
  • ✅ Parallel loading for performance

Planned:

  • 🚧 Detect cycles in requirement graphs
  • 🚧 Trigger reviews when dependent requirements change
  • 🚧 Generate coverage reports (requirement → implementation → test)
  • 🚧 Import and export in standard formats

Contributions are welcome! See the GitHub repository for more information.

Design Philosophy

Requiem is built on several core principles:

  1. Plain text first - Requirements are markdown files that can be read, edited, and reviewed without special tools
  2. Git-friendly - Every requirement change creates a meaningful diff that's easy to review in pull requests
  3. Dual identifiers - Stable UUIDs for machine processing, human-readable IDs (like USR-001) for people
  4. Fast by default - Parallel processing and efficient data structures mean Requiem scales to large projects
  5. Composable - Works alongside your existing documentation tools rather than replacing them
  6. Documentation tool friendly - HRIDs are stored in markdown headings (e.g., # USR-001 Title) for seamless integration with Sphinx and MdBook

Who This Guide Is For

This guide is designed for:

  • Requirements engineers managing formal requirement sets
  • Technical writers documenting software systems
  • Developers working in regulated environments
  • Project managers needing traceability and impact analysis
  • QA engineers mapping requirements to test cases

You should be comfortable with:

  • Command-line tools
  • Text editors
  • Basic version control (Git)
  • Markdown formatting

What's in This Guide

This guide includes:

  • User Guide: Learn how to use Requiem effectively
  • Reference: Detailed CLI and file format specifications
  • Example Project: See Requiem managing its own requirements as a real-world example

The Example Project contains all 21 requirements that define what Requiem does, demonstrating traceability, proper structure, and best practices.

Let's get started!

Getting Started

This section will help you install Requiem and create your first requirements project. By the end, you'll understand the basic workflow and be ready to manage your own requirements.

The following chapters cover:

If you're eager to dive in, start with the Quick Start Tutorial. If you prefer a more thorough understanding, read through all three chapters in order.

Installation

Requiem is distributed as a Rust crate and can be installed using Cargo, Rust's package manager.

Prerequisites

You'll need Rust installed on your system. If you don't have it yet:

Installing Rust

Visit rustup.rs or run:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

After installation, verify Rust is available:

rustc --version
cargo --version

Installing Requiem

From crates.io

Once Rust is installed, install Requiem using Cargo:

cargo install requirements-manager

This will download, compile, and install the req command-line tool.

From Source

To install the latest development version from the GitHub repository:

cargo install --git https://github.com/danieleades/requirements-manager

Verify Installation

Confirm Requiem is installed correctly:

req --version

You should see output like:

req 0.1.0

Getting Help

To see all available commands:

req --help

For help with a specific command:

req add --help
req link --help

Updating Requiem

To update to the latest version:

cargo install requirements-manager --force

The --force flag tells Cargo to reinstall even if a version is already present.

Uninstalling

To remove Requiem:

cargo uninstall requirements-manager

Next Steps

Now that Requiem is installed, proceed to the Quick Start Tutorial to learn the basic commands.

Quick Start Tutorial

This 5-minute tutorial introduces Requiem's basic workflow. You'll create a simple set of requirements and link them together.

Creating a Requirements Directory

First, create a directory for your requirements:

mkdir my-requirements
cd my-requirements

Requiem works with any directory - there's no special initialization needed. Requirements are simply markdown files with YAML frontmatter.

Adding Your First Requirement

Let's create a user requirement using the add command:

req add USR

This creates a file named USR-001.md with automatically generated metadata. Output:

Added requirement USR-001

The file contains:

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001


The YAML frontmatter includes:

  • _version: Format version for future compatibility
  • uuid: A globally unique, stable identifier
  • created: Timestamp of creation

The heading includes:

  • # USR-001: The HRID as the first token in the first heading
  • Followed by the title text (currently empty)

The body (currently empty) is where you'll write the requirement text.

Editing the Requirement

Open USR-001.md in your text editor and add content:

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001 Plain Text Requirements

The system shall support plain-text requirements that can be edited with any text editor.

Notice the HRID (USR-001) appears as the first token in the first heading, followed by the title. Save the file. That's it! You've created your first requirement.

Adding More Requirements

Create a few more user requirements:

req add USR  # Creates USR-002
req add USR  # Creates USR-003

Edit these files to add meaningful content. For example:

USR-002.md:

---
_version: '1'
uuid: ...
created: ...
---
# USR-002 Version Control Integration

The system shall integrate with version control systems like Git.

USR-003.md:

---
_version: '1'
uuid: ...
created: ...
---
# USR-003 Requirement Traceability

The system shall support requirement traceability and linkage.

Creating System Requirements

Now let's create system-level requirements that satisfy the user requirements:

req add SYS  # Creates SYS-001

Linking Requirements

Link SYS-001 to its parent USR-001:

req link SYS-001 USR-001

Output:

Linked SYS-001 to USR-001

Now if you open SYS-001.md, you'll see the parent relationship in the frontmatter and the HRID in the heading:

---
_version: '1'
uuid: 81e63bac-4035-47b5-b273-ac13e47a2ff6
created: 2025-07-22T13:14:40.510075462Z
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001
---
# SYS-001 Markdown File Format

Each requirement shall be stored as a markdown file with YAML frontmatter.

The parents section contains:

  • uuid: The stable identifier of the parent
  • hrid: The human-readable ID (for your convenience)
  • fingerprint: A hash of the parent's content (for change detection)

Creating Requirements with Multiple Parents

You can link a requirement to multiple parents when creating it:

req add SYS --parents USR-001,USR-002

This creates SYS-002 already linked to both USR-001 and USR-002.

Viewing Requirements

Requirements are just markdown files, so you can view them with any tool:

ls *.md
cat USR-001.md

Or use your favorite text editor, IDE, or markdown viewer.

Summary

You've learned the three core commands:

  1. req add <KIND> - Create a new requirement
  2. req link <CHILD> <PARENT> - Link two requirements
  3. req add <KIND> --parents <PARENT1>,<PARENT2> - Create with parents

These commands form the foundation of requirements management with Requiem.

Next Steps

Continue to Your First Requirements Project to build a complete requirement hierarchy and learn more advanced techniques.

Your First Requirements Project

In this chapter, we'll build a complete requirements hierarchy for a simple project: a task management application. You'll learn how to structure requirements across multiple levels and establish traceability.

Planning the Hierarchy

A typical requirements hierarchy has multiple levels:

  1. User Requirements (USR) - High-level needs from the user's perspective
  2. System Requirements (SYS) - Technical specifications that satisfy user needs
  3. Software Requirements (SWR) - Detailed implementation requirements (optional)
  4. Test Requirements (TST) - Test cases that verify requirements (optional)

For our task app, we'll use USR and SYS levels.

Setting Up the Project

Create and enter a new directory:

mkdir task-app-requirements
cd task-app-requirements

Creating User Requirements

User requirements describe what users need, not how it's implemented.

req add USR  # USR-001
req add USR  # USR-002
req add USR  # USR-003

Edit each file to add content:

USR-001.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
---
# USR-001 Create Tasks

Users shall be able to create tasks with a title and description.

USR-002.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
---
# USR-002 Mark Tasks Complete

Users shall be able to mark tasks as complete.

USR-003.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
---
# USR-003 Filter Tasks

Users shall be able to filter tasks by completion status.

Creating System Requirements

System requirements break down user requirements into technical specifications.

For USR-001 (creating tasks), we need:

req add SYS --parents USR-001  # SYS-001
req add SYS --parents USR-001  # SYS-002

SYS-001.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
parents:
- uuid: <USR-001 uuid>
  fingerprint: <auto-generated>
  hrid: USR-001
---
# SYS-001 Task Data Structure

The system shall provide a Task data structure with fields: id, title, description, completed, created_at.

SYS-002.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
parents:
- uuid: <USR-001 uuid>
  fingerprint: <auto-generated>
  hrid: USR-001
---
# SYS-002 Task Title Validation

The system shall validate that task titles are non-empty strings with maximum 100 characters.

For USR-002 (marking complete):

req add SYS --parents USR-002  # SYS-003

SYS-003.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
parents:
- uuid: <USR-002 uuid>
  fingerprint: <auto-generated>
  hrid: USR-002
---
# SYS-003 Toggle Task Completion

The system shall provide a method to toggle the completed status of a task.

For USR-003 (filtering):

req add SYS --parents USR-003  # SYS-004

SYS-004.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
parents:
- uuid: <USR-003 uuid>
  fingerprint: <auto-generated>
  hrid: USR-003
---
# SYS-004 Filter Tasks by Status

The system shall provide a method to filter tasks returning only those matching the specified completion status.

Creating Cross-Cutting Requirements

Some requirements affect multiple user needs. For example, persistence:

req add SYS --parents USR-001,USR-002,USR-003  # SYS-005

SYS-005.md:

---
_version: '1'
uuid: <auto-generated>
created: <auto-generated>
parents:
- uuid: <USR-001 uuid>
  fingerprint: <auto-generated>
  hrid: USR-001
- uuid: <USR-002 uuid>
  fingerprint: <auto-generated>
  hrid: USR-002
- uuid: <USR-003 uuid>
  fingerprint: <auto-generated>
  hrid: USR-003
---
# SYS-005 Task Persistence

The system shall persist all tasks to disk and load them on startup.

This requirement has three parents because it affects creating, completing, and filtering tasks.

Reviewing Your Requirements Structure

Your directory now contains:

task-app-requirements/
├── USR-001.md  (Create tasks)
├── USR-002.md  (Mark complete)
├── USR-003.md  (Filter tasks)
├── SYS-001.md  → USR-001 (Task data structure)
├── SYS-002.md  → USR-001 (Title validation)
├── SYS-003.md  → USR-002 (Toggle completed)
├── SYS-004.md  → USR-003 (Filter method)
└── SYS-005.md  → USR-001, USR-002, USR-003 (Persistence)

Version Control Integration

Requirements are plain text, so they work great with Git:

git init
git add *.md
git commit -m "Initial requirements for task management app"

Every requirement change will now show up in your Git history with clear diffs:

--- a/USR-001.md
+++ b/USR-001.md
@@ -4,4 +4,4 @@
 created: 2025-07-22T12:19:56.950194157Z
 ---

-Users shall be able to create tasks with a title and description.
+Users shall be able to create tasks with a title, description, and due date.

Best Practices Demonstrated

This example shows several best practices:

  1. Start high-level - Begin with user requirements before diving into technical details
  2. One concept per requirement - Each requirement addresses a single, testable concept
  3. Use clear language - Requirements use "shall" to indicate mandatory behavior
  4. Establish traceability - Every system requirement traces to at least one user requirement
  5. Support multiple parents - Cross-cutting concerns can satisfy multiple needs

Next Steps

Now that you understand the basics, explore:

Continue reading to learn how Requiem supports advanced requirements management practices.

Core Concepts

Requirements management is a discipline with well-established principles and practices. This chapter explores these concepts and shows how Requiem implements them.

Understanding these principles will help you:

  • Structure requirements effectively
  • Maintain traceability throughout the development lifecycle
  • Manage changes systematically
  • Collaborate effectively with stakeholders

Chapters

Whether you're new to requirements management or an experienced practitioner, these chapters will ground you in the "why" behind Requiem's features.

Requirements Management Principles

Effective requirements management is built on several foundational principles. Understanding these helps you structure your requirements for maximum value.

What is a Requirement?

A requirement is a documented statement of a need, constraint, or capability that a system must satisfy. Requirements answer the question: "What must the system do or be?"

Good requirements are:

  • Clear - Unambiguous and understandable by all stakeholders
  • Testable - You can verify whether the system satisfies the requirement
  • Necessary - The requirement addresses a genuine need
  • Feasible - The requirement can realistically be implemented
  • Traceable - The requirement can be tracked through the development lifecycle

Requirement Levels

Requirements typically exist at multiple levels of abstraction:

User Requirements

High-level statements of user needs and goals. Written in user terminology, these describe what users need to accomplish, not how.

Example: "Users shall be able to export data in multiple formats."

System Requirements

Technical specifications derived from user requirements. These describe how the system will satisfy user needs.

Example: "The system shall provide export functionality supporting CSV, JSON, and XML formats."

Software/Hardware Requirements

Detailed requirements for specific subsystems or components.

Example: "The export module shall use the serde library for JSON serialization."

Requirement Attributes

Each requirement should have metadata:

  • Unique Identifier - A stable reference (e.g., USR-001)
  • Status - Draft, approved, implemented, verified, etc.
  • Priority - Critical, high, medium, low
  • Owner - Person or team responsible
  • Rationale - Why this requirement exists
  • Source - Where the requirement came from

Note: Requiem currently stores identifiers and timestamps. Status, priority, and other attributes can be added as tags or in the requirement body.

Traceability

Traceability is the ability to track relationships between requirements and other artifacts (design documents, code, tests). There are two types:

  • Forward traceability - From requirements to design, code, and tests
  • Backward traceability - From code and tests back to requirements

Traceability enables:

  • Impact analysis (what breaks if we change this requirement?)
  • Coverage analysis (are all requirements implemented and tested?)
  • Compliance verification (can we prove we met all requirements?)

Requirement Dependencies

Requirements rarely exist in isolation. They form a directed graph where:

  • Parent (upstream) requirements - Higher-level needs that must be satisfied
  • Child (downstream) requirements - Detailed specifications that satisfy parents

Example:

USR-001: "Users shall authenticate securely"
  └─ SYS-001: "System shall use OAuth 2.0"
       └─ SWR-001: "Use the oauth2-rs library"

The V-Model

The V-Model visualizes how requirements flow through development:

User Requirements  ←→  Acceptance Tests
       ↓                      ↑
System Requirements ←→ Integration Tests
       ↓                      ↑
Software Requirements ←→ Unit Tests
       ↓                      ↑
    Implementation

Each level of requirements corresponds to a level of testing that verifies those requirements.

Requirements vs. Design

A common challenge is distinguishing requirements from design:

  • Requirement - WHAT the system must do
  • Design - HOW the system will do it

Example:

  • ❌ Requirement: "The system shall use a PostgreSQL database" (This is design)
  • ✅ Requirement: "The system shall persist data reliably across restarts" (This is a requirement)
  • ✅ Design: "We'll use PostgreSQL to satisfy the persistence requirement" (This is design)

However, in some contexts (particularly lower levels), the line blurs. "System shall use OAuth 2.0" might be a legitimate requirement if it's mandated by stakeholders or regulations.

Change Management

Requirements change. Good requirements management accepts this and provides mechanisms to:

  1. Track changes - Know what changed, when, and why
  2. Analyze impact - Understand what's affected by a change
  3. Trigger reviews - Ensure dependent requirements and tests are updated
  4. Maintain history - Preserve the evolution of requirements

Validation vs. Verification

Two distinct but related concepts:

  • Validation - Are we building the right thing? (Do requirements match user needs?)
  • Verification - Are we building the thing right? (Does implementation match requirements?)

Validation often involves stakeholder reviews. Verification involves testing and inspection.

Why These Principles Matter

Following these principles provides:

  • Clarity - Everyone understands what's being built
  • Accountability - Clear ownership and traceability
  • Quality - Testable requirements lead to better testing
  • Agility - Understanding impact enables confident change
  • Compliance - Proof that requirements are met

Requiem's Approach

Requiem embodies these principles through:

  • Plain-text markdown for clarity and accessibility
  • YAML frontmatter for metadata and relationships
  • UUID-based traceability with human-readable aliases
  • Content fingerprinting for change detection
  • Multiple parent support for complex dependencies

Continue to Traceability to see how Requiem implements these concepts in practice.

Traceability

Traceability is the cornerstone of requirements management. It's the ability to track relationships between requirements and other artifacts throughout the development lifecycle.

Why Traceability Matters

Traceability enables:

  1. Impact Analysis - If requirement X changes, what else is affected?
  2. Coverage Analysis - Are all requirements implemented? Tested?
  3. Compliance - Prove that every requirement has been satisfied
  4. Root Cause Analysis - Trace bugs back to requirements
  5. Change Management - Understand dependencies before making changes

Types of Traceability

Vertical Traceability

Tracks relationships between levels of requirements:

Stakeholder Needs
       ↓
User Requirements (USR)
       ↓
System Requirements (SYS)
       ↓
Software Requirements (SWR)

Example:

  • Stakeholder: "We need to reduce data entry errors"
  • USR-042: "Users shall receive validation feedback"
  • SYS-078: "Form inputs shall validate on blur events"
  • SWR-123: "Use the validator.js library for email validation"

Horizontal Traceability

Tracks relationships within the same level:

USR-001 ← USR-005
USR-001 ← USR-012

Example: USR-005 and USR-012 might both depend on USR-001's authentication requirement.

Forward Traceability

From requirements downstream to:

  • Design documents
  • Source code
  • Test cases
  • User documentation

Example: USR-001 → SYS-042 → test_authentication.rs

Backward Traceability

From implementation artifacts upstream to requirements:

test_login.py → SYS-042 → USR-001

This answers: "Why does this test exist?" or "Which requirement does this code satisfy?"

Traceability in Requiem

Requiem implements vertical traceability through explicit parent-child relationships:

---
_version: '1'
uuid: ccdbddbe-d5d2-4656-b4fe-85e61c02cf63
created: 2025-07-22T13:15:27.996136510Z
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001
---

The system shall validate user credentials using bcrypt hashing.

This SYS requirement explicitly traces to its parent USR-001.

Stable Identifiers (UUIDs)

Each requirement has a UUID that never changes, even if the requirement is renumbered or renamed. This enables reliable traceability over time.

uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a  # Stable forever
hrid: USR-001                                # Might change

Human-Readable IDs (HRIDs)

While UUIDs are stable, HRIDs like USR-001 make traceability human-friendly:

  • Easy to reference in conversations: "Did you implement USR-042?"
  • Clear in code comments: // Satisfies SYS-078
  • Readable in reports: "Coverage: 45 of 52 SYS requirements implemented"

Multiple Parents

Unlike many tools, Requiem supports multiple parent requirements:

parents:
- uuid: <uuid-1>
  hrid: USR-001
- uuid: <uuid-2>
  hrid: USR-003
- uuid: <uuid-3>
  hrid: USR-007

This reflects reality: a single implementation often satisfies multiple needs.

Example: A logging system might satisfy requirements for debugging, auditing, and compliance - three different parent needs.

Traceability Beyond Requiem

Requiem manages requirement-to-requirement traceability. For complete lifecycle traceability, you need:

Requirement → Code

Manual approach: Add requirement IDs in comments:

#![allow(unused)]
fn main() {
// Satisfies: SYS-042, SYS-043
fn validate_email(email: &str) -> Result<(), ValidationError> {
    // ...
}
}

Automated approach: Use code analysis tools to extract these tags and build traceability matrices.

Requirement → Tests

Manual approach: Reference requirements in test names or docstrings:

#![allow(unused)]
fn main() {
#[test]
fn test_usr_042_email_validation() {
    // Verifies USR-042: Email validation feedback
}
}

Automated approach: Tools can parse test names and generate coverage reports.

Requirement → Documentation

When using Requiem with MdBook or Sphinx, you can embed requirements directly in user documentation:

## Plain Text Storage

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001 Plain Text Storage

## Statement

The tool shall store requirements as plain-text files that can be read and edited with any text editor.

## Rationale

Plain text storage enables:
- Version control integration with Git and other VCS tools
- Human review without specialized software
- Long-term archival and accessibility
- Integration with existing text-based workflows

## Acceptance Criteria

- Requirements are stored as `.md` (Markdown) files
- Files can be opened and edited in any text editor
- No proprietary or binary formats are required
- Files are compatible with standard version control systems

Requirements are stored as simple markdown files.

This ensures documentation stays synchronized with requirements.

Traceability Challenges

Manual traceability is prone to drift:

  • Code changes but requirement IDs in comments aren't updated
  • Tests are renamed and traceability is lost

Mitigation: Automate checks in CI. Use tools to validate that referenced requirement IDs exist.

Granularity

How fine-grained should traceability be?

  • Too coarse: "This module satisfies USR-001 through USR-050" (not helpful)
  • Too fine: "This line satisfies requirement X clause 2.3.1.4" (maintenance nightmare)

Balance: Trace at the function/class level for code, at the test case level for tests.

Many-to-Many Relationships

Real systems have complex relationships:

  • One requirement satisfied by multiple components
  • One component satisfying multiple requirements

Requiem's multiple-parent support helps, but complete traceability requires additional tooling.

Traceability Reports

Note: Automated report generation is planned but not yet implemented in Requiem.

Common traceability reports include:

Coverage Matrix

RequirementDesignedImplementedTestedStatus
USR-001Complete
USR-002Missing Tests
USR-003Not Implemented

Dependency Graph

Visual representation of requirement relationships, showing the complete hierarchy from stakeholder needs down to implementation.

Impact Report

Given a changed requirement, list all downstream requirements, design documents, code, and tests that might be affected.

Best Practices

  1. Link early - Establish traceability when creating requirements, not as an afterthought
  2. Use consistent formats - Standardize how you reference requirements in code and tests
  3. Automate verification - Add CI checks that validate traceability links
  4. Review regularly - Periodically audit traceability to catch drift
  5. Keep it simple - Traceability is valuable only if maintained; avoid overly complex schemes

Next Steps

Understanding traceability enables effective change management. Continue to Change Management to learn how Requiem helps you manage evolving requirements.

Change Management

Requirements change. Users discover new needs, technology evolves, regulations update, and understanding deepens. Effective requirements management doesn't fight change - it embraces and manages it.

Why Requirements Change

Common drivers of change:

  • Evolving understanding - Stakeholders clarify needs as they see prototypes
  • External factors - New regulations, competitor features, market shifts
  • Technical discoveries - Implementation reveals previously unknown constraints
  • Scope refinement - Priorities shift as the project progresses
  • Error correction - Requirements contained mistakes or ambiguities

Change Management Goals

Effective change management aims to:

  1. Track changes - Know what changed, when, and why
  2. Analyze impact - Understand ripple effects before committing
  3. Notify stakeholders - Alert affected parties
  4. Trigger reviews - Ensure dependent artifacts are updated
  5. Maintain history - Preserve the evolution for audit and learning

Requiem's Change Management Features

Content Fingerprinting

Every requirement has a fingerprint - a SHA256 hash of its content:

parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001

When a parent requirement changes, its fingerprint changes. This allows child requirements to detect that their parent has been modified.

How Fingerprinting Works

The fingerprint is computed from:

  • The requirement's text content (markdown body)
  • Any tags on the requirement

It does not include:

  • UUID (never changes)
  • HRID (might be renumbered)
  • Creation timestamp
  • Parent relationships

This means fingerprints change only when meaningful content changes.

Detecting Changes

When a parent requirement is edited, its fingerprint becomes stale in child requirements:

# Parent USR-001 was edited, fingerprint is now abc123...
# But child still references old fingerprint:
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda  # Old!
  hrid: USR-001

Note: Automated detection of stale fingerprints and triggering reviews is planned but not yet implemented.

Version Control Integration

Requiem's plain-text format provides powerful change management through Git:

Viewing Changes

git diff USR-001.md

Shows exactly what changed:

-Users shall be able to create tasks with a title and description.
+Users shall be able to create tasks with a title, description, and due date.

Change History

git log --follow USR-001.md

Shows complete history of a requirement, including:

  • Who changed it
  • When it changed
  • Why (from commit messages)

Blame/Annotate

git blame USR-001.md

Shows who last modified each line, useful for finding the source of specific clauses.

Change Workflow

A typical requirement change workflow:

1. Propose Change

Create a branch:

git checkout -b update-authentication-requirements

Edit the requirement:

# USR-001.md
-Users shall authenticate using username and password.
+Users shall authenticate using username and password, or via OAuth providers (Google, GitHub).

2. Analyze Impact

Identify affected requirements:

# Find requirements that reference USR-001
grep -r "USR-001" *.md

Review child requirements to see if they need updates:

  • SYS-042: "System shall hash passwords with bcrypt" - Still valid
  • SYS-043: "System shall rate-limit login attempts" - Needs OAuth rate limiting too!

3. Update Dependent Requirements

Update child requirements to reflect the change:

# SYS-043.md
-The system shall rate-limit password login attempts to 5 per minute.
+The system shall rate-limit authentication attempts to 5 per minute, including both password and OAuth flows.

4. Review and Approve

Create a pull request:

git add USR-001.md SYS-043.md
git commit -m "Add OAuth authentication to USR-001 and update rate limiting in SYS-043"
git push origin update-authentication-requirements

The PR shows:

  • Exact changes (diff)
  • Affected requirements
  • Commit message explaining rationale

Stakeholders review and approve.

5. Merge and Notify

After approval, merge the PR. Git history preserves:

  • What changed
  • When it changed
  • Who approved it
  • Why it changed (commit message)

Change Impact Analysis

Understanding the impact of a change is crucial. Requiem helps through:

Parent-Child Relationships

If requirement X changes, all child requirements may be affected. Review each to determine if updates are needed.

Multiple Parents

When a requirement has multiple parents and one changes, evaluate:

  • Does the change conflict with other parents?
  • Do child requirements still satisfy all parents?

Example:

USR-001: "Fast performance"
USR-002: "Strong encryption"
   └─ SYS-042: "Use AES-256 encryption"

If USR-001 changes to require sub-millisecond response times, SYS-042's encryption choice might need reconsideration (encryption adds latency).

Review Triggers

Note: Automated review triggering is planned but not yet implemented.

In the future, Requiem will support:

Automatic Review Flags

When a requirement changes:

  1. Its fingerprint updates
  2. Child requirements detect stale fingerprints
  3. Those requirements are flagged for review
  4. Reviews can be assigned to stakeholders
  5. Requirements are approved or updated
  6. Fingerprints are refreshed

Review States

Possible states:

  • Current - Fingerprint matches parent
  • Suspect - Parent changed, review needed
  • Under Review - Assigned for review
  • Approved - Reviewed and still valid despite parent change

Best Practices

1. Write Meaningful Commit Messages

# Bad
git commit -m "Update requirements"

# Good
git commit -m "Add due date support to USR-001 per stakeholder feedback from 2025-10-15 meeting"

Reference issue trackers in commits:

git commit -m "Update authentication requirements (resolves #42)"

3. Review Dependent Requirements

When changing a requirement, always:

  • Search for references to its HRID
  • Review child requirements
  • Check related documentation
  • Update tests

4. Use Branches for Changes

Never modify requirements directly on main:

  • Create a branch
  • Make changes
  • Get review
  • Merge

This creates an audit trail and enables discussion before commitment.

If changing USR-001 requires updating SYS-042 and SYS-043, do it in one commit:

git add USR-001.md SYS-042.md SYS-043.md
git commit -m "Extend authentication to support OAuth (USR-001, SYS-042, SYS-043)"

This preserves the logical relationship between changes.

Change Metrics

Useful metrics for requirement stability:

  • Churn rate - How often requirements change
  • Ripple effect - Average number of requirements affected by a change
  • Review latency - Time from change to review completion
  • Approval rate - Percentage of proposed changes accepted

High churn in high-level requirements (USR) may indicate poor initial understanding. High churn in low-level requirements (SWR) may be normal as implementation details evolve.

Handling Breaking Changes

Some changes invalidate child requirements:

Example: USR-001 requires "single-user application," but later changes to "multi-user application."

SYS requirements assuming single-user (no authentication, shared global state) are now invalid.

Process:

  1. Mark affected requirements as "obsolete" or delete them
  2. Create new requirements for multi-user scenario
  3. Update traceability links
  4. Document the change rationale

Next Steps

Now that you understand how requirements change, see how Requiem's design supports these practices: How Requiem Supports These Principles

How Requiem Supports These Principles

Now that you understand requirements management principles, let's explore how Requiem's design choices support these practices.

Plain Text: The Foundation

Requiem's most fundamental decision is storing requirements as plain text (Markdown with YAML frontmatter).

Benefits

Human Readable: Anyone with a text editor can read and edit requirements. No specialized tools required.

---
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
---

Users shall be able to export data in CSV format.

This is instantly understandable to developers, managers, and stakeholders alike.

Version Control Native: Plain text integrates seamlessly with Git, providing:

  • Line-by-line diffs showing exactly what changed
  • Complete history with blame and log
  • Pull request workflows for review
  • Branching and merging for parallel development

Tool Agnostic: Requirements aren't locked into proprietary formats. You can:

  • Search with grep/ripgrep
  • Process with scripts (Python, Bash, etc.)
  • View in any text editor or IDE
  • Preview as rendered Markdown
  • Process with static site generators

Future Proof: Plain text files from 1970 are still readable today. Your requirements will outlive any proprietary tool.

Trade-offs

No GUI: Requiem doesn't provide a graphical interface. Users must be comfortable with text editors and the command line.

No Real-time Collaboration: Unlike cloud-based tools, Requiem doesn't support simultaneous editing. Use Git workflows instead.

Dual Identifiers: Stability and Usability

Requiem uses both UUIDs and Human-Readable IDs (HRIDs).

UUIDs: Stable References

uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a

Purpose: Permanent, globally unique identifier that never changes.

Enables:

  • Renumbering requirements without breaking links
  • Merging requirement sets from different sources
  • Machine processing and indexing

Example: You can rename USR-001 to AUTH-001 without breaking any parent references, because they use the UUID.

HRIDs: Human Communication

hrid: USR-001

Purpose: Short, memorable identifier for human use.

Enables:

  • Easy verbal communication: "Did you implement USR-042?"
  • Clear code comments: // Satisfies SYS-078
  • Intuitive filenames: USR-001.md

Example: In a meeting, saying "UUID 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a" is impractical. "USR-001" is clear and concise.

Best of Both Worlds

Parent relationships use UUIDs but store HRIDs for convenience:

parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a  # For machine processing
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001  # For human readers

The req clean command corrects HRIDs if requirements are renumbered, maintaining human-readability while UUIDs ensure correctness.

Content Fingerprinting: Change Detection

Every requirement's content is hashed to create a fingerprint:

fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda

How It Works

The fingerprint is a SHA256 hash of:

  • The requirement text (markdown body)
  • Any tags

This means:

  • ✓ Changing the requirement text → new fingerprint
  • ✓ Adding/removing tags → new fingerprint
  • ✗ Changing HRID → same fingerprint (HRID is just a label)
  • ✗ Adding parents → same fingerprint (relationships are separate)

Enables Change Detection

When a parent requirement changes:

  1. Parent's fingerprint updates
  2. Children still have old fingerprint
  3. Children are "suspect" - they might need review

Note: Automatic detection is planned but not yet implemented. Currently, you detect stale fingerprints manually or via scripts.

Future: Review Workflows

Planned features:

  • Automatically flag requirements with stale parent fingerprints
  • Assign reviews to stakeholders
  • Track review status (current, suspect, under review, approved)
  • Generate reports of suspect requirements

Multiple Parents: Modeling Reality

Many requirements management tools force a strict tree hierarchy. Requiem supports multiple parents because that's how real systems work.

Why Multiple Parents Matter

Example: A logging system might satisfy:

  • USR-042: "Debugging capability"
  • USR-078: "Audit trail for compliance"
  • USR-091: "Performance monitoring"

Representing this as a tree forces artificial choices:

# Tree (artificial)
USR-042 (Debugging)
  └─ SYS-123 (Logging)  # Also satisfies USR-078 and USR-091, but structure doesn't show this

With multiple parents:

SYS-123 (Logging)
  ├─ USR-042 (Debugging)
  ├─ USR-078 (Audit trail)
  └─ USR-091 (Performance monitoring)

This accurately models the requirement's purpose.

Implementation

parents:
- uuid: <uuid-1>
  hrid: USR-042
- uuid: <uuid-2>
  hrid: USR-078
- uuid: <uuid-3>
  hrid: USR-091

Trade-off: Cycles

Multiple parents enable cycles (requirement A depends on B depends on A). Cycles are usually errors.

Note: Cycle detection is planned but not yet implemented.

Namespace Support: Scaling to Large Projects

HRIDs support optional namespaces:

USR-001              # Simple
COMPONENT-USR-001    # One namespace level
AUTH-LOGIN-SYS-042   # Multiple namespace levels

Use Cases

Large projects: Partition requirements by subsystem

AUTH-USR-001    # Authentication user requirements
AUTH-SYS-001
PAYMENT-USR-001 # Payment user requirements
PAYMENT-SYS-001

Product families: Distinguish product-specific vs. shared requirements

CORE-SYS-001    # Shared across all products
MOBILE-USR-001  # Mobile app specific
WEB-USR-001     # Web app specific

Acquisitions/Mergers: Integrate requirement sets without renumbering

LEGACY-SYS-001  # From acquired company
NEW-SYS-001     # Newly created

Implementation

Namespaces are part of the HRID format:

#![allow(unused)]
fn main() {
// Format: {NAMESPACE*}-{KIND}-{ID}
NAMESPACE-NAMESPACE-KIND-042
}

Configure allowed namespaces in config.toml (optional).

Configuration and Flexibility

Requiem provides sane defaults but allows customization:

config.toml

_version = "1"

# Restrict to specific requirement kinds
allowed_kinds = ["USR", "SYS", "SWR", "TST"]

# Digits in HRID numbering (e.g., 001 vs 0001)
digits = 3

# Allow markdown files that aren't requirements
allow_unrecognised = false

# Allow requirements with invalid format
allow_invalid = false

This balances flexibility (customize as needed) with safety (defaults prevent common errors).

Integration Philosophy: Compose, Don't Replace

Requiem integrates with existing tools rather than replacing them:

Documentation Tools

Use with MdBook or Sphinx to embed requirements in user documentation:

# User Guide - Data Export

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001 Plain Text Storage

## Statement

The tool shall store requirements as plain-text files that can be read and edited with any text editor.

## Rationale

Plain text storage enables:
- Version control integration with Git and other VCS tools
- Human review without specialized software
- Long-term archival and accessibility
- Integration with existing text-based workflows

## Acceptance Criteria

- Requirements are stored as `.md` (Markdown) files
- Files can be opened and edited in any text editor
- No proprietary or binary formats are required
- Files are compatible with standard version control systems

To export data, click the Export button...

Requirements stay synchronized with documentation automatically.

Version Control

Works naturally with Git workflows:

  • Feature branches for requirement changes
  • Pull requests for review
  • Merge commits for approval
  • Tags for releases/versions

Static Analysis

Plain-text enables custom tooling:

# Find all USR requirements not linked by any SYS requirement
comm -23 \
  <(ls USR-*.md | sort) \
  <(grep -oh "USR-[0-9]*" SYS-*.md | sort -u)

CI/CD Integration

Add requirement validation to CI:

# .github/workflows/requirements.yml
- name: Validate requirements
  run: req clean --dry-run  # Check HRIDs are correct

Performance: Built for Scale

Requiem is written in Rust and uses parallelism for operations on large requirement sets.

Parallel Loading

When loading a directory with thousands of requirements:

#![allow(unused)]
fn main() {
// Uses rayon for parallel iteration
let requirements: Vec<_> = md_paths
    .par_iter()
    .map(|path| load_requirement(path))
    .collect();
}

This means Requiem scales to large projects (1000s of requirements) without becoming sluggish.

Efficient Indexing

Requirements are indexed by UUID in a HashMap, enabling O(1) lookups:

#![allow(unused)]
fn main() {
let req = tree.requirement(uuid);  // Constant time
}

Design Trade-offs

Every design involves trade-offs. Requiem prioritizes:

Over graphical interfaces: Plain text and CLI

  • Pro: Version control, scripting, no vendor lock-in
  • Con: Steeper learning curve for non-technical users

Over centralized databases: Distributed files

  • Pro: Works offline, natural with Git, simple deployment
  • Con: No real-time collaboration, requires file system access

Over strict tree hierarchies: Multiple parents (DAGs)

  • Pro: Models reality accurately
  • Con: Enables cycles (requires detection)

Over comprehensive built-in features: Composability

  • Pro: Integrate with existing tools, stay focused
  • Con: Some features require external tools or scripts

Summary: Why Requiem?

Requiem's design supports requirements management principles through:

  1. Plain text - Readable, versionable, future-proof
  2. Dual identifiers - Stable UUIDs + usable HRIDs
  3. Fingerprinting - Detect changes, enable reviews
  4. Multiple parents - Model complex dependencies accurately
  5. Namespace support - Scale to large, multi-component projects
  6. Composable - Works with Git, MdBook, Sphinx, custom tools
  7. Fast - Parallel processing for large requirement sets

These choices make Requiem a powerful tool for teams that value:

  • Version control integration
  • Plain-text workflows
  • Speed and scalability
  • Flexibility and composability

Ready to dive deeper into practical usage? Continue to Working with Requirements.

Working with Requirements

This chapter covers the practical aspects of using Requiem day-to-day. You'll learn the requirement file format, how to create and link requirements, and how to manage complex requirement relationships.

Chapters

By the end of this chapter, you'll be proficient in all core Requiem operations.

Requirement File Format

Requiem requirements are stored as markdown files with YAML frontmatter. This chapter explains the format in detail.

File Structure

A requirement file has three parts:

  1. YAML Frontmatter - Metadata enclosed in --- delimiters
  2. HRID Title - The HRID as the first token in the first markdown heading
  3. Markdown Body - The requirement text

Example

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
---
# SYS-001 Email Validation

The system shall validate user email addresses according to RFC 5322.

Email validation must occur before account creation.

HRID in Title

Important: The HRID (Human-Readable ID) must appear as the first token in the first markdown heading:

# USR-001 Plain Text Storage
# SYS-042 Email Validation System
# AUTH-LOGIN-SYS-001 Password Hashing

Key points:

  • The HRID is the first token (word) in the heading
  • Followed by a space and then the title text
  • The HRID is NOT in the YAML frontmatter
  • This format ensures compatibility with Sphinx and MdBook

Why this matters: This change was made to improve compatibility with documentation tools like Sphinx and MdBook, which can use the heading as the page title naturally.

YAML Frontmatter

The frontmatter contains structured metadata.

Required Fields

_version

_version: '1'

Purpose: Format version for future compatibility.

Value: Currently always '1' (quoted string).

Why it matters: If Requiem's file format evolves, this field allows newer versions to handle older files correctly.

uuid

uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a

Purpose: Globally unique, stable identifier.

Value: UUIDv4 (automatically generated by req add).

Why it matters: This never changes, even if the requirement is renumbered. Parent-child relationships use UUIDs, ensuring links remain valid.

created

created: 2025-07-22T12:19:56.950194157Z

Purpose: Timestamp of requirement creation.

Value: ISO 8601 format with timezone (always UTC).

Why it matters: Provides audit trail and helps understand requirement evolution.

Optional Fields

parents

parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
- uuid: 7a8f9e2b-1c3d-4e5f-6a7b-8c9d0e1f2a3b
  fingerprint: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
  hrid: USR-003

Purpose: Links to parent (upstream) requirements.

Value: List of parent objects, each containing:

  • uuid - Parent's stable identifier
  • fingerprint - SHA256 hash of parent's content
  • hrid - Parent's human-readable ID (for convenience)

Why it matters: Establishes traceability. Multiple parents are supported.

Note: This field is absent if the requirement has no parents (e.g., top-level user requirements).

tags (planned)

tags:
- security
- authentication
- high-priority

Purpose: Categorize and filter requirements.

Status: The data structure supports tags, but there are no CLI commands to manage them yet. You can manually add tags to the YAML.

Future: Commands like req tag add USR-001 security will manage tags.

Markdown Body

The body contains the actual requirement text, written in Markdown.

Best Practices

Use Clear Language

# Good
The system shall validate email addresses before account creation.

# Less clear
Email validation is performed.

Use "shall" for mandatory requirements, "should" for recommended, "may" for optional.

One Concept Per Requirement

# Bad (multiple concepts)
The system shall validate emails and passwords and usernames.

# Good (split into separate requirements)
# USR-001.md
The system shall validate email addresses.

# USR-002.md
The system shall validate passwords for minimum strength.

# USR-003.md
The system shall validate usernames for uniqueness.

Be Testable

# Bad (not testable)
The system shall be fast.

# Good (testable)
The system shall respond to login requests within 200ms at the 95th percentile.

Include Context

The system shall hash passwords using bcrypt with a cost factor of 12.

Rationale: Bcrypt is resistant to GPU-based attacks. Cost factor 12 provides
security while maintaining acceptable login performance (< 200ms).

Markdown Features

You can use any Markdown syntax:

Headings

The first heading must contain the HRID. Subsequent headings are free-form:

# USR-001 User Authentication

## Rationale

The requirement exists because...

## Acceptance Criteria

- Criterion 1
- Criterion 2

Lists

The system shall support the following authentication methods:

1. Username and password
2. OAuth (Google, GitHub)
3. SAML SSO

Code Blocks

Example API response:

\`\`\`json
{
  "user_id": "4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a",
  "email": "user@example.com"
}
\`\`\`

Emphasis

The system **shall** validate emails. It *should* provide helpful error messages.

Filename Convention

Filenames must match the requirement's HRID:

USR-001.md
SYS-042.md
COMPONENT-SUBCOMPONENT-SWR-123.md

Case sensitive: USR-001.md and usr-001.md are different files (though the latter won't be recognized as a requirement).

Extension: Must be .md.

HRID Consistency: The HRID in the filename should match the HRID in the first heading. For example, USR-001.md should contain # USR-001 Title. The filename is authoritative for determining the HRID.

If the filename doesn't match the HRID format, Requiem will:

  • Ignore the file (if allow_unrecognised = true in config)
  • Return an error (if allow_unrecognised = false, the default)

Parsing Rules

Frontmatter Delimiters

The YAML frontmatter must:

  • Start with --- on the first line
  • End with --- on a line by itself
  • Contain valid YAML
---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---

Requirement text here...

Whitespace

  • Leading/trailing whitespace in the body is preserved
  • Empty lines between frontmatter and body are ignored
---
...frontmatter...
---


This is the first line of the body (empty lines above are ignored).

Editing Requirements

Manual Editing

You can edit requirements with any text editor:

vim USR-001.md
code SYS-042.md
nano TST-003.md

Caution: Don't modify the uuid field! This would break traceability.

Safe to edit:

  • The markdown body (requirement text)
  • Tags (if present)

Requiem manages (don't edit manually):

  • created timestamp
  • Parent fingerprint fields (updated by linking commands)

Using Scripts

Since requirements are plain text, you can process them with scripts:

# Add a tag to all USR requirements
import re
import glob

for filename in glob.glob("USR-*.md"):
    with open(filename, 'r') as f:
        content = f.read()

    # Add tag to frontmatter
    content = content.replace(
        "---\n",
        "---\ntags:\n- user-facing\n",
        1  # Only first occurrence
    )

    with open(filename, 'w') as f:
        f.write(content)

Caution: Ensure scripts preserve YAML validity. Invalid YAML will cause parsing errors.

Validation

Requiem validates requirements when loading:

req clean  # Loads all requirements, reports errors

Common validation errors:

  • Invalid YAML: Syntax errors in frontmatter
  • Missing required fields: No uuid, created, or _version
  • Invalid UUID: Malformed UUID string
  • Invalid timestamp: Malformed ISO 8601 date
  • Duplicate UUIDs: Two requirements with the same UUID (serious error!)

File Format Evolution

The _version field allows future format changes:

Version 1 (current):

  • Fields: _version, uuid, created, parents, tags
  • Parents include UUID, fingerprint, and HRID

Version 2 (hypothetical future):

  • Might add: status, priority, owner
  • Older Requiem versions can still read V1 files

Real-World Examples

Want to see actual requirement files following this format? Browse the Example Project which contains 21 real requirements used by Requiem itself:

These demonstrate the file format in practice with proper frontmatter, parent links, and well-structured content.

Next Steps

Now that you understand the file format, learn about Human-Readable IDs (HRIDs) and their syntax rules.

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/category
  • ID = 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:

  1. Filename: USR-001.md, COMPONENT-SYS-042.md
  2. 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.

Creating Requirements

The req add command creates new requirements with automatically generated metadata.

Basic Usage

req add <KIND>

This creates a requirement with the next available ID for the specified KIND.

Examples

# Create USR-001
req add USR

# Create USR-002
req add USR

# Create SYS-001
req add SYS

Output:

Added requirement USR-001
Added requirement USR-002
Added requirement SYS-001

Command Options

Specify Parent Requirements

Create a requirement already linked to parents:

req add <KIND> --parents <PARENT1>,<PARENT2>,...

Alias: -p for --parents

Examples

# Create SYS-001 linked to USR-001
req add SYS --parents USR-001

# Create SYS-002 linked to both USR-001 and USR-002
req add SYS --parents USR-001,USR-002

# Using short form
req add SYS -p USR-001,USR-002

Specify Root Directory

By default, req operates in the current directory. Use --root to specify a different directory:

req --root /path/to/requirements add USR

Alias: -r for --root

This is useful when running Requiem from outside the requirements directory:

# Run from project root
req --root ./docs/requirements add USR

# Using short form
req -r ./docs/requirements add USR

Verbosity

Control log output:

req -v add USR      # INFO level
req -vv add USR     # DEBUG level
req -vvv add USR    # TRACE level

More v's = more verbose. Useful for troubleshooting.

Generated Content

When you run req add USR, a file USR-001.md is created with:

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001


Generated fields:

  • _version: Always '1' (current format version)
  • uuid: A random UUIDv4
  • created: Current timestamp in ISO 8601 format (UTC)
  • # USR-001: First heading with HRID (title text is initially empty)

Empty body: You need to add the requirement title and text yourself.

Adding Content

After creating a requirement, edit it to add content:

req add USR
# Output: Added requirement USR-001

# Edit the file
vim USR-001.md
# or
code USR-001.md

Add your requirement title and text:

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001 CSV Export

Users shall be able to export data in CSV format.

## Rationale

CSV is a universally supported format for data interchange.

Note that the HRID (USR-001) is the first token in the heading, followed by the title. Save the file. Your requirement is now complete.

Creating with Parents

When you specify parents, they're included in the frontmatter:

req add SYS --parents USR-001

Creates SYS-001.md:

---
_version: '1'
uuid: 81e63bac-4035-47b5-b273-ac13e47a2ff6
created: 2025-07-22T13:14:40.510075462Z
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001
---
# SYS-001


Generated parent fields:

  • uuid: Copied from USR-001's UUID
  • fingerprint: Computed from USR-001's current content
  • hrid: USR-001 (for human readability in frontmatter)

Generated heading:

  • # SYS-001: First heading with HRID (you'll add the title text when editing)

Multiple Parents

req add SYS --parents USR-001,USR-002,USR-003

Creates SYS-001.md with three parent entries:

parents:
- uuid: <USR-001 UUID>
  fingerprint: <USR-001 fingerprint>
  hrid: USR-001
- uuid: <USR-002 UUID>
  fingerprint: <USR-002 fingerprint>
  hrid: USR-002
- uuid: <USR-003 UUID>
  fingerprint: <USR-003 fingerprint>
  hrid: USR-003

Using Namespaces

Create requirements with namespaces by including them in the KIND:

# Create AUTH-USR-001
req add AUTH-USR

# Create AUTH-LOGIN-SYS-001
req add AUTH-LOGIN-SYS

# Create PAYMENT-API-SWR-001
req add PAYMENT-API-SWR

The filename matches the full HRID:

AUTH-USR-001.md
AUTH-LOGIN-SYS-001.md
PAYMENT-API-SWR-001.md

Workflow Recommendations

Create High-Level First

Start with user requirements:

req add USR
req add USR
req add USR

Edit them to add content. Then create system requirements that satisfy them:

req add SYS --parents USR-001
req add SYS --parents USR-001
req add SYS --parents USR-002

This top-down approach ensures traceability from the start.

Create in Batches

If you know you need five user requirements:

for i in {1..5}; do req add USR; done

This creates USR-001 through USR-005. Then edit each file to add content.

Use Version Control

After creating requirements, commit them:

req add USR
req add USR
git add USR-001.md USR-002.md
git commit -m "Add initial user requirements (placeholders)"

# Edit the files, then commit again
git add USR-001.md USR-002.md
git commit -m "Add content to USR-001 and USR-002"

This creates a clear history of requirement evolution.

Error Conditions

Parent Not Found

req add SYS --parents USR-999

If USR-999.md doesn't exist, you'll get an error:

Error: Failed to load requirement USR-999

Solution: Ensure parent requirements exist before linking to them.

Invalid HRID Format

req add usr-001  # Trying to specify ID manually (not supported)

The KIND should not include the ID. Use:

req add USR  # Correct - ID is auto-assigned

Malformed Parent List

req add SYS --parents USR-001, USR-002  # Space after comma

Don't include spaces in the parent list:

req add SYS --parents USR-001,USR-002  # Correct

Advanced: Scripting Requirement Creation

For bulk creation with structured content, use shell scripts:

#!/bin/bash

# Create and populate multiple user requirements
requirements=(
  "Users shall authenticate via username and password"
  "Users shall reset forgotten passwords via email"
  "Users shall enable two-factor authentication"
)

for i in "${!requirements[@]}"; do
  req add USR
  hrid="USR-$(printf '%03d' $((i+1)))"

  # Append requirement text to the file
  echo "${requirements[$i]}" >> "$hrid.md"
done

This creates USR-001, USR-002, and USR-003 with predefined content.

Next Steps

Once you've created requirements, you'll often need to link them together. Learn how in Linking Requirements.

Templates

Templates provide default body content when creating new requirements, helping maintain consistency across your requirements documentation.

Overview

When you create a new requirement using req add <KIND>, the tool looks for a template file in the .req/templates/ directory. If found, the template content is used as the body of the new requirement. The HRID is automatically generated, and the title can be provided via the --title flag or edited after creation.

Template Location

Templates are stored as markdown files in the .req/templates/ directory:

your-requirements/
├── .req/
│   └── templates/
│       ├── USR.md          # Template for USR requirements
│       ├── SYS.md          # Template for SYS requirements
│       └── AUTH-USR.md     # Template for AUTH-USR requirements
├── config.toml
├── USR-001.md
└── SYS-001.md

Template Matching

When creating a requirement, templates are matched in order of specificity:

  1. Full prefix match: If creating AUTH-USR-001, looks for .req/templates/AUTH-USR.md
  2. KIND-only match: If not found, looks for .req/templates/USR.md
  3. No template: If neither exists, creates empty content

This allows you to:

  • Define general templates for kinds (e.g., USR.md for all user requirements)
  • Override with namespace-specific templates (e.g., AUTH-USR.md for auth user requirements)

Creating Templates

Templates should contain body content only, starting with level-2 headings (##). The level-1 heading with HRID and title is automatically generated by the tool.

Simple Text Template

The simplest template is just plain text:

[Describe the requirement here]

Save this as .req/templates/USR.md.

Structured Template

For more structure, use markdown sections starting with level-2 headings:

## Description

[Detailed description]

## Acceptance Criteria

- [ ] Criterion 1
- [ ] Criterion 2

## Notes

[Additional notes]

Important: Do not include a level-1 heading (#) in templates. The tool automatically generates the heading with the HRID.

Namespace-Specific Template

Create specialized templates for namespaced requirements:

## Security Considerations

[Describe security implications]

## Implementation

[Authentication mechanism details]

## Test Strategy

[How to verify this auth requirement]

Save this as .req/templates/AUTH-USR.md.

Using Templates

Automatic Template Application

When you create a requirement without content flags, the template body is automatically used:

# Without title - creates requirement with empty title and template body
req add USR

# With title - creates requirement with specified title and template body
req add USR --title "User Registration"

The generated file will have this structure:

---
_version: '1'
uuid: ...
created: ...
---
# USR-001 User Registration

[Template body content starts here]

Overriding Templates

Templates are ignored when you provide content via CLI flags:

# Template ignored - uses title and body from flags
req add USR -t "Custom Title" -b "Custom content"

# Template ignored - uses title from flag
req add USR -t "Custom Title"

# Template ignored - uses body from flag
req add USR -b "Custom content"

Examples

Software Project Templates

.req/templates/USR.md:

## Statement

[Describe the user-facing requirement]

## User Value

[Why does the user need this?]

## Acceptance Criteria

- [ ] Criterion 1
- [ ] Criterion 2

.req/templates/SYS.md:

## Statement

[Describe the system-level implementation requirement]

## Technical Notes

[Implementation details]

## Testing

[How to verify]

Aerospace Project Templates

.req/templates/URQT.md (User Requirements):

## Description

[User requirement description]

## Rationale

[Justification]

## Verification Method

[Test, Analysis, Inspection, or Demonstration]

.req/templates/SRQT.md (Software Requirements):

## Specification

[Detailed technical specification]

## Derived From

[Parent URQT reference]

## Verification Method

[Test method]

## Criticality

[DAL level]

Best Practices

Keep Templates Simple

Templates should provide structure without being overly prescriptive:

✓ Good: [Describe the requirement]

✗ Too prescriptive: The system SHALL [verb] [object] [condition]

Use Placeholders

Use square brackets for clear placeholders:

[Describe the requirement here]

**Rationale**: [Why is this needed?]

Team Conventions

Document your team's template conventions:

## Description
[One paragraph summary]

## Details
[Detailed specification with sub-sections as needed]

## Testing
[How to verify this requirement]

Version Control

Commit templates to version control alongside your requirements:

git add .req/templates/
git commit -m "Add requirement templates"

Updating Templates

Templates only affect new requirements. To update existing requirements:

  1. Update the template file
  2. Manually edit existing requirements to match (if desired)
  3. Or use the template as a guide for new requirements only

Common Patterns

Minimal Templates

For projects that prefer freeform text:

[Requirement description]

Structured Templates

For projects requiring specific sections:

## Specification
[Technical details]

## Rationale
[Why this is needed]

## Verification
[How to test]

Compliance Templates

For regulated industries:

## Requirement
[Requirement text]

## Compliance
**Standard**: [e.g., DO-178C]
**Criticality**: [e.g., DAL A]

## Verification
**Method**: [Test, Analysis, Inspection, Demonstration]
**Criteria**: [Pass/fail criteria]

Troubleshooting

Template Not Being Used

Problem: Created requirement is empty even though template exists.

Check:

  1. Template file is in .req/templates/ directory
  2. Template filename matches KIND exactly (case-sensitive)
  3. Template file has .md extension
  4. You didn't use -t or -b flags (which override templates)

Wrong Template Being Used

Problem: Expected namespace-specific template but got general template.

Reason: Namespace-specific template file doesn't exist.

Solution: Create .req/templates/<NAMESPACE>-<KIND>.md

Example: For AUTH-USR-001, create .req/templates/AUTH-USR.md

Real-World Example

Want to see templates in action? Check out the templates used by the Requiem project itself:

  • USR Template - User requirements template with Statement, Rationale, and Acceptance Criteria sections
  • SYS Template - System requirements template with Statement, Implementation Notes, and Verification sections

These templates are used to create all requirements in the Example Project, demonstrating professional structure and best practices.

Linking Requirements

The req link command establishes parent-child relationships between requirements, creating traceability throughout your requirement hierarchy.

Basic Usage

req link <CHILD> <PARENT>

This adds PARENT to CHILD's parent list.

Example

req link SYS-001 USR-001

Output:

Linked SYS-001 to USR-001

Now SYS-001.md contains:

---
_version: '1'
uuid: 81e63bac-4035-47b5-b273-ac13e47a2ff6
created: 2025-07-22T13:14:40.510075462Z
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001
---

...requirement content...

Multiple Parents

You can link a child to multiple parents by running req link multiple times:

req link SYS-001 USR-001
req link SYS-001 USR-002
req link SYS-001 USR-003

Now SYS-001.md has three parents:

parents:
- uuid: <USR-001 UUID>
  fingerprint: <USR-001 fingerprint>
  hrid: USR-001
- uuid: <USR-002 UUID>
  fingerprint: <USR-002 fingerprint>
  hrid: USR-002
- uuid: <USR-003 UUID>
  fingerprint: <USR-003 fingerprint>
  hrid: USR-003

Linking at Creation Time

Instead of linking after creation, you can specify parents when creating:

# Instead of:
req add SYS
req link SYS-001 USR-001
req link SYS-001 USR-002

# Do:
req add SYS --parents USR-001,USR-002

This is more efficient and ensures traceability from the start.

What Gets Updated

When you run req link CHILD PARENT:

  1. CHILD file is modified: The parent entry is added to the YAML frontmatter
  2. PARENT file is NOT modified: Parent doesn't know about its children

This is a directed relationship: children point to parents, not vice versa.

Finding Children

To find all children of a requirement, search files:

grep -l "hrid: USR-001" *.md

This shows all requirements that list USR-001 as a parent.

Parent Information

Each parent entry contains three fields:

UUID (Required)

uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a

The stable, unique identifier of the parent. This is the canonical reference that enables reliable traceability even if the parent is renumbered.

Fingerprint (Required)

fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda

A SHA256 hash of the parent's content at the time of linking. This enables change detection:

  • Parent content changes → fingerprint changes
  • Child still has old fingerprint → signals that parent has changed
  • Child should be reviewed to ensure it's still valid

HRID (Required)

hrid: USR-001

The human-readable ID of the parent. This is for convenience when reading the YAML. The actual relationship is based on the UUID.

If the parent is renumbered, the HRID can be corrected with req clean (covered in Maintaining Requirements).

Linking Across Namespaces

You can link requirements with different namespaces:

req link PAYMENT-SYS-001 CORE-USR-001

The namespaces don't need to match. Links are based on UUIDs, which are globally unique across all namespaces.

Error Conditions

Child Not Found

req link SYS-999 USR-001

If SYS-999.md doesn't exist:

Error: Failed to load requirement SYS-999

Parent Not Found

req link SYS-001 USR-999

If USR-999.md doesn't exist:

Error: Failed to load requirement USR-999

Linking a child to the same parent twice:

req link SYS-001 USR-001
req link SYS-001 USR-001

This creates duplicate entries in the parent list. Avoid this by checking existing links before adding new ones.

Note: Duplicate detection is not currently implemented but may be added in future versions.

Typical Linking Patterns

One-to-Many (Parent → Children)

One user requirement satisfied by multiple system requirements:

USR-001
  ├─ SYS-001
  ├─ SYS-002
  └─ SYS-003
req add USR
req add SYS --parents USR-001
req add SYS --parents USR-001
req add SYS --parents USR-001

Many-to-One (Parents → Child)

One system requirement satisfying multiple user requirements:

USR-001 ─┐
USR-002 ─┼─ SYS-001
USR-003 ─┘
req add USR
req add USR
req add USR
req add SYS --parents USR-001,USR-002,USR-003

Many-to-Many

Complex dependencies:

USR-001 ─┬─ SYS-001
         └─ SYS-002
USR-002 ─┬─ SYS-002
         └─ SYS-003
req add SYS --parents USR-001
req add SYS --parents USR-001,USR-002
req add SYS --parents USR-002

Best Practices

# Preferred
req add SYS --parents USR-001

# Works but requires two commands
req add SYS
req link SYS-001 USR-001

Establish Traceability Early

Link requirements as you create them, not as an afterthought. This ensures your hierarchy is always traceable.

Document Linking Rationale

In the requirement body, explain why each parent link exists:

---
parents:
- hrid: USR-001
  ...
- hrid: USR-003
  ...
---

The system shall provide OAuth authentication.

Satisfies USR-001 (secure login) and USR-003 (third-party integration).

When reviewing requirement changes, check that:

  • New requirements link to appropriate parents
  • Links are not duplicated
  • Parent requirements actually exist

Unlinking (Not Yet Supported)

Currently, there's no req unlink command. To remove a parent link, manually edit the child file:

# Before
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001
- uuid: 7a8f9e2b-1c3d-4e5f-6a7b-8c9d0e1f2a3b
  fingerprint: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
  hrid: USR-002

# After (removed USR-002)
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001

Be careful to preserve valid YAML syntax.

Since links aren't bidirectional in the files, you may want to generate visual representations:

# Simple script to list parent-child relationships
for file in *.md; do
  hrid=$(basename "$file" .md)
  parents=$(grep "hrid:" "$file" | awk '{print $2}')
  for parent in $parents; do
    echo "$parent -> $hrid"
  done
done

Output:

USR-001 -> SYS-001
USR-001 -> SYS-002
USR-002 -> SYS-002

You can pipe this to graph visualization tools like Graphviz.

Next Steps

Learn how to work with complex requirement relationships in Managing Relationships.

Managing Relationships

As your requirements grow, the dependency graph becomes complex. This chapter covers strategies for managing intricate requirement relationships.

Understanding Requirement Graphs

Requirements form a directed acyclic graph (DAG):

  • Directed: Parent-child relationships have a direction (child → parent)
  • Acyclic: No circular dependencies (requirement A → B → C → A)
  • Graph: Nodes (requirements) connected by edges (parent-child links)

Note: Cycle detection is planned but not yet implemented. Currently, you must avoid cycles manually.

Hierarchical Levels

A typical hierarchy has 3-5 levels:

Stakeholder Needs
        ↓
User Requirements (USR)
        ↓
System Requirements (SYS)
        ↓
Software Requirements (SWR) / Hardware Requirements (HWR)
        ↓
Test Requirements (TST)

Each level derives from the one above and is verified by the one below.

Complex Relationships

Cross-Cutting Requirements

Some requirements affect multiple areas:

USR-001 (Login feature) ─┐
USR-002 (Data export)    ├─ SYS-042 (Logging)
USR-003 (Admin panel)    ┘

Logging satisfies needs from login (debug), export (audit), and admin (monitoring).

Implementation:

req add SYS --parents USR-001,USR-002,USR-003

Derived Requirements

One parent spawns many children:

USR-001 (Secure authentication)
  ├─ SYS-001 (Password hashing)
  ├─ SYS-002 (Rate limiting)
  ├─ SYS-003 (Session management)
  └─ SYS-004 (OAuth support)

Implementation:

req add USR
req add SYS --parents USR-001  # SYS-001
req add SYS --parents USR-001  # SYS-002
req add SYS --parents USR-001  # SYS-003
req add SYS --parents USR-001  # SYS-004

Composite Requirements

Multiple parents combine into one child:

SYS-010 (User data API)   ─┐
SYS-015 (Auth middleware) ─┼─ SWR-042 (Protected endpoint implementation)
SYS-022 (JSON serialization)─┘

Implementation:

req add SWR --parents SYS-010,SYS-015,SYS-022

Traceability Queries

Finding relationships in a large requirement set:

Find All Children of a Requirement

grep -l "hrid: USR-001" *.md

Lists all files that have USR-001 as a parent.

Find All Parents of a Requirement

grep "hrid:" SYS-042.md | awk '{print $2}'

Extracts parent HRIDs from SYS-042.

Find Requirements Without Parents

for file in SYS-*.md; do
  if ! grep -q "^parents:" "$file"; then
    echo "$file has no parents"
  fi
done

Identifies top-level requirements at a given level (might be an error).

Find Requirements Without Children

for usr in USR-*.md; do
  hrid=$(basename "$usr" .md)
  if ! grep -q "hrid: $hrid" SYS-*.md; then
    echo "$hrid has no children"
  fi
done

Finds user requirements not satisfied by any system requirements (coverage gap).

Avoiding Common Problems

Circular Dependencies

Problem: A → B → C → A creates a cycle.

req link B A
req link C B
req link A C  # Creates cycle!

Detection (manual): Trace parent chains to ensure they terminate.

Prevention: Enforce strict hierarchy levels (USR → SYS → SWR → TST, never backward).

Note: Automatic cycle detection is planned.

Orphaned Requirements

Problem: Requirements with no parents or children.

USR with no children: Unimplemented user needs (coverage gap).

SYS with no parents: Requirements without justification (why does this exist?).

Detection: Use the scripts above to find orphans.

Problem: Skipping levels in the hierarchy.

USR-001 → SWR-042  # Skips SYS level!

Prevention: Enforce that USR links only to SYS, SYS links only to SWR, etc.

Exception: Sometimes justified in small projects, but generally avoided.

Problem: Too many fine-grained requirements with complex links.

SYS-001 (Email validation)
  ├─ SWR-001 (Regex pattern)
  ├─ SWR-002 (Error message)
  ├─ SWR-003 (UI feedback)
  ├─ SWR-004 (Logging)
  └─ SWR-005 (Internationalization)

Solution: Combine related low-level requirements or accept coarser traceability.

Refactoring Requirements

As understanding evolves, you may need to restructure:

Splitting a Requirement

Original:

USR-001: Users shall authenticate and manage their profiles.

Split into:

USR-001: Users shall authenticate securely.
USR-002: Users shall manage their profile information.

Process:

  1. Create new requirement (USR-002)
  2. Update child requirements to link to appropriate parent
  3. Update original requirement text
  4. Mark as obsolete or delete if no longer needed

Merging Requirements

Two requirements are redundant:

USR-001: Users shall export data.
USR-003: Users shall download reports.

Process:

  1. Choose one to keep (USR-001)
  2. Update its text to cover both concepts
  3. Relink children of USR-003 to USR-001
  4. Delete USR-003

Reorganizing Hierarchy

Moving requirements between levels or namespaces:

Before:

SYS-042: OAuth integration

After:

AUTH-SYS-042: OAuth integration

Process:

  1. Rename file: mv SYS-042.md AUTH-SYS-042.md
  2. Run req clean to update HRIDs in child requirements
  3. Manually update any external references (documentation, code comments)

Documentation Strategies

Requirement Specification Documents

Generate human-readable specs from requirements:

# Simple concatenation
cat USR-*.md > user-requirements.md
cat SYS-*.md > system-requirements.md

Traceability Matrices

Create tables showing parent-child relationships:

User ReqSystem Reqs
USR-001SYS-001, SYS-002, SYS-003
USR-002SYS-002, SYS-004
USR-003SYS-005

Generate with scripts:

for usr in USR-*.md; do
  hrid=$(basename "$usr" .md)
  children=$(grep -l "hrid: $hrid" SYS-*.md | sed 's/.md//' | paste -sd,)
  echo "| $hrid | $children |"
done

Visual Dependency Graphs

Use Graphviz to visualize relationships:

echo "digraph requirements {"
for file in *.md; do
  child=$(basename "$file" .md)
  grep "hrid:" "$file" | awk -v child="$child" '{print "  " $2 " -> " child}'
done
echo "}"

Output:

digraph requirements {
  USR-001 -> SYS-001
  USR-001 -> SYS-002
  USR-002 -> SYS-002
  USR-002 -> SYS-003
}

Render with:

./generate-graph.sh | dot -Tpng > requirements-graph.png

Scalability Considerations

Large Projects (100s of requirements)

  • Use namespaces to partition by component
  • Generate indexes and matrices automatically
  • Consider directory structure: auth/USR-*.md, payment/USR-*.md

Very Large Projects (1000s of requirements)

  • Parallel loading (Requiem does this automatically)
  • External database for complex queries
  • Dedicated requirements management integration tools

Multi-Product Families

  • Shared requirements in CORE-*
  • Product-specific in MOBILE-*, WEB-*, etc.
  • Cross-reference shared requirements from product-specific ones

Best Practices Summary

  1. Maintain strict hierarchy - USR → SYS → SWR → TST
  2. Document cross-cutting concerns - Explain why a requirement has many parents
  3. Avoid cycles - Keep relationships acyclic
  4. Review orphans regularly - Find requirements without links
  5. Refactor thoughtfully - Restructure as understanding evolves
  6. Automate traceability checks - Use scripts in CI
  7. Visualize complex graphs - Generate diagrams for stakeholder review

Real-World Example

See traceability in action in the Example Project, where you can explore:

  • USR-006 (Requirement Templates) traces to 5 system requirements (SYS-011 through SYS-015)
  • USR-004 (Graph Analysis) traces to 5 system requirements (SYS-004, 005, 008, 009, 010)
  • Multiple requirements with single parents, demonstrating various relationship patterns

Browse the User Requirements page to see the complete traceability tree visualized.

Next Steps

Learn how to configure Requiem for your project in Configuration.

Configuration

Requiem provides sensible defaults but allows customization through configuration files and directory structure.

This chapter covers:

Proper configuration helps Requiem adapt to your project's needs.

Configuration File

Requiem uses a TOML configuration file named config.toml in the root of your requirements directory to customize behavior.

Location

The configuration file must be named config.toml and placed in the root directory where your requirements are stored:

my-requirements/
├── config.toml       ← Configuration file
├── USR-001.md
├── USR-002.md
└── SYS-001.md

If no configuration file exists, Requiem uses sensible defaults and continues without error.

File Format

The configuration file is written in TOML (Tom's Obvious Minimal Language), a simple, human-readable format.

Minimal Example

The simplest valid configuration:

_version = "1"

This accepts all defaults. The _version field is required for future format compatibility.

Complete Example

A configuration using all available options:

_version = "1"

# Restrict requirement kinds
allowed_kinds = ["USR", "SYS", "SWR", "TST"]

# Number of digits in HRID numbering
digits = 3

# Allow non-requirement markdown files
allow_unrecognised = false

# Allow requirements with invalid formatting
allow_invalid = false

Configuration Options

_version (required)

_version = "1"

Type: String (quoted)

Default: N/A (required field)

Purpose: Specifies the configuration format version. This enables future format changes while maintaining backward compatibility.

Current version: "1" (as a string, not a number)

Example:

_version = "1"  # Correct

Invalid:

_version = 1    # Wrong: must be a quoted string

allowed_kinds (optional)

allowed_kinds = ["USR", "SYS", "SWR", "TST"]

Type: Array of strings

Default: [] (empty array = all kinds allowed)

Purpose: Restricts which requirement kinds (the KIND component of HRIDs) are permitted in your project.

When to use:

  • Enforce project standards (e.g., only USR, SYS, TST requirements allowed)
  • Prevent typos (USR-001 vs. UST-001)
  • Document your requirement taxonomy

Behavior:

  • Empty array (default): Any kind is accepted
  • Non-empty array: Only listed kinds are valid

Example - Aerospace project:

allowed_kinds = ["URQT", "SRQT", "SWRQT", "HWRQT", "TEST"]
# User Requirements (URQT), System Requirements (SRQT), etc.

Example - Software project:

allowed_kinds = ["USR", "SYS", "SWR", "TST", "DOC"]

Enforcement: When allowed_kinds is non-empty, attempting to create a requirement with a disallowed kind will fail:

$ req add INVALID
Error: Kind 'INVALID' is not in the allowed list

digits (optional)

digits = 3

Type: Unsigned integer

Default: 3

Purpose: Specifies the minimum number of digits used in HRID numbering. IDs are zero-padded to this width.

Valid values: Any positive integer, though 3 or 4 are most common.

Behavior:

With digits = 3:

USR-001
USR-002
...
USR-099
USR-100  # Exceeds 3 digits when needed

With digits = 4:

USR-0001
USR-0002
...
USR-9999
USR-10000  # Exceeds 4 digits when needed

Choosing a value:

  • digits = 3: Projects with < 1000 requirements per kind
  • digits = 4: Projects with 1000+ requirements per kind
  • digits = 5: Very large projects

Note: This setting affects display format only. Parsing accepts any number of digits:

  • USR-1, USR-01, USR-001 all parse as ID 1
  • Display format uses the configured padding

Example - Large project:

digits = 4
# Requirements display as USR-0001, USR-0002, etc.

allow_unrecognised (optional)

allow_unrecognised = false

Type: Boolean

Default: false

Purpose: Controls whether markdown files that don't match the HRID pattern are allowed in the requirements directory.

Behavior:

false (default - strict mode):

  • Only files matching the HRID pattern (e.g., USR-001.md) are allowed
  • Any other .md file causes an error during loading
  • Ensures clean, requirements-only directory

true (permissive mode):

  • Files with non-HRID names are silently ignored
  • Useful when requirements live alongside other documentation

When to use true:

Integration with documentation tools:

docs/
├── config.toml          ← allow_unrecognised = true
├── introduction.md      ← Ignored (not an HRID)
├── architecture.md      ← Ignored
├── USR-001.md          ← Loaded as requirement
└── USR-002.md          ← Loaded as requirement

Mixed content repositories:

project-docs/
├── README.md           ← Ignored
├── CHANGELOG.md        ← Ignored
├── requirements/
│   ├── USR-001.md      ← Loaded
│   └── SYS-001.md      ← Loaded

When to use false (default):

  • Dedicated requirements directory
  • Strict separation between requirements and other docs
  • Catch typos (e.g., US-001.md instead of USR-001.md)

Error example with allow_unrecognised = false:

$ req clean
Error: Unrecognised file: README.md

allow_invalid (optional)

allow_invalid = false

Type: Boolean

Default: false

Purpose: Controls whether requirement files with invalid YAML frontmatter or formatting errors are allowed.

Behavior:

false (default - strict mode):

  • Requirements must have valid YAML frontmatter
  • Missing required fields cause errors
  • Ensures data integrity

true (permissive mode):

  • Invalid requirements are skipped with warnings
  • Partial loading allows working with partially correct data
  • Useful during migration or recovery

Validation checks:

  • Valid YAML syntax
  • Required fields present (_version, uuid, created)
  • Valid UUID format
  • Valid timestamp format
  • Valid parent structure (if present)

When to use true:

  • Migrating from another tool (gradual fix-up)
  • Recovering from manual editing errors
  • Development/debugging

When to use false (default):

  • Production use
  • Ensure data quality
  • Catch errors early

Error example with allow_invalid = false:

$ req clean
Error: Invalid requirement USR-001.md: missing required field 'uuid'

Warning example with allow_invalid = true:

$ req clean
Warning: Skipping invalid requirement USR-001.md: missing required field 'uuid'
Successfully loaded 42 requirements (1 skipped)

Configuration Strategy

Start Simple

Begin with minimal configuration:

_version = "1"

Add constraints as your project matures.

Small project (< 100 requirements):

_version = "1"
digits = 3
allow_unrecognised = false
allow_invalid = false

Large project (> 1000 requirements):

_version = "1"
allowed_kinds = ["USR", "SYS", "SWR", "HWR", "TST", "DOC"]
digits = 4
allow_unrecognised = false
allow_invalid = false

Integrated documentation project:

_version = "1"
allowed_kinds = ["USR", "SYS"]
digits = 3
allow_unrecognised = true  # Mixed with other docs
allow_invalid = false

Migration project:

_version = "1"
digits = 3
allow_unrecognised = true
allow_invalid = true  # Temporarily permissive during migration

Validation

Validate your configuration by running:

req clean

This loads all requirements and reports configuration-related errors.

Successful validation:

$ req clean
# No output = success

Configuration error:

$ req clean
Error: Failed to parse config file: missing field '_version'

Configuration Examples

Regulated Industry (Aerospace)

_version = "1"

# DO-178C levels: User, System, Software, Hardware, Test
allowed_kinds = ["URQT", "SRQT", "SWRQT", "HWRQT", "TRQT"]

# Large project
digits = 4

# Strict validation
allow_unrecognised = false
allow_invalid = false

Agile Software Project

_version = "1"

# User stories, system reqs, tests
allowed_kinds = ["USR", "SYS", "TST"]

# Small/medium project
digits = 3

# Allow flexibility
allow_unrecognised = false
allow_invalid = false

Multi-Component System

_version = "1"

# Component-prefixed kinds
allowed_kinds = [
    "USR",           # Cross-cutting user requirements
    "AUTH-SYS",      # Authentication subsystem
    "PAY-SYS",       # Payment subsystem
    "REPORT-SYS",    # Reporting subsystem
]

digits = 3
allow_unrecognised = false
allow_invalid = false

Troubleshooting

Config file not recognized

Problem: Changes to config.toml don't take effect.

Solution: Ensure the file is named exactly config.toml (lowercase, no extra extensions) and is in the requirements root directory.

Parse errors

Problem: Error: Failed to parse config file

Solution: Validate TOML syntax:

  • Strings must be quoted: _version = "1", not _version = 1
  • Arrays use square brackets: allowed_kinds = ["USR", "SYS"]
  • Check for typos in field names

Use a TOML validator or linter if needed.

Unexpected behavior

Problem: Requirements are rejected unexpectedly.

Solution:

  1. Check allowed_kinds - ensure the kinds you're using are listed
  2. Check allow_unrecognised - set to true if mixing requirements with other docs
  3. Check allow_invalid - consider temporarily enabling for debugging

Future Configuration Options

Planned configuration options (not yet implemented):

  • namespace_separator: Customize the separator in namespaced HRIDs
  • require_namespaces: Enforce namespace usage
  • max_parents: Limit number of parent requirements
  • tag_validation: Restrict allowed tag values
  • review_policies: Configure review workflow behavior

Next Steps

Directory Structure

Requiem is flexible about how you organize requirements on disk. This chapter explains directory organization options and best practices.

Directory Structure Modes

Requiem supports two fundamental modes for organizing requirements, controlled by the subfolders_are_namespaces configuration option:

1. Filename-Based Mode (Default)

Configuration: subfolders_are_namespaces = false (or omitted)

In this mode, the full HRID is encoded in the filename, and directory structure is purely organizational:

my-requirements/
├── USR-001.md              → HRID: USR-001
├── SYS-002.md              → HRID: SYS-002
├── auth-USR-003.md         → HRID: auth-USR-003
└── custom/folder/
    └── system-REQ-004.md   → HRID: system-REQ-004

Use when: You want maximum flexibility in folder organization without affecting requirement namespaces.

2. Path-Based Mode

Configuration: subfolders_are_namespaces = true

In this mode, subfolders encode the namespace, and the filename contains only KIND-ID:

my-requirements/
├── REQ-001.md              → HRID: REQ-001 (no namespace)
├── system/
│   └── auth/
│       ├── REQ-002.md      → HRID: system-auth-REQ-002
│       └── USR/
│           └── 003.md      → HRID: system-auth-USR-003 (KIND from parent)

The filename format is automatically inferred:

  • Numeric only (e.g., 003.md) → KIND taken from parent folder
  • KIND-ID (e.g., REQ-002.md) → KIND and ID from filename

Use when: You want folder structure to directly mirror requirement namespaces.

Basic Structure

At minimum, you need a directory containing requirement markdown files:

my-requirements/
├── USR-001.md
├── USR-002.md
├── SYS-001.md
└── SYS-002.md

That's it! No initialization or hidden directories required.

With Configuration

Add a config.toml for project-specific settings:

my-requirements/
├── config.toml      ← Configuration
├── USR-001.md
├── USR-002.md
├── SYS-001.md
└── SYS-002.md

The configuration file is optional but recommended for projects with specific needs.

Using Subdirectories

Requiem recursively searches subdirectories, enabling hierarchical organization.

Organize by Requirement Kind

requirements/
├── config.toml
├── user/
│   ├── USR-001.md
│   ├── USR-002.md
│   └── USR-003.md
├── system/
│   ├── SYS-001.md
│   ├── SYS-002.md
│   └── SYS-003.md
└── test/
    ├── TST-001.md
    └── TST-002.md

Advantages:

  • Clear separation of requirement levels
  • Easy to navigate
  • Natural for large projects

Note: In filename-based mode (default), directory names don't affect requirement behavior. user/USR-001.md and system/USR-001.md would create a filename conflict (both have HRID USR-001), so use different kinds. In path-based mode, these would have different HRIDs: user-USR-001 and system-USR-001.

Organize by Feature

requirements/
├── config.toml
├── authentication/
│   ├── USR-001.md   # User login
│   ├── SYS-001.md   # Auth service
│   └── TST-001.md   # Auth tests
├── payment/
│   ├── USR-002.md   # Payment processing
│   ├── SYS-002.md   # Payment gateway
│   └── TST-002.md   # Payment tests
└── reporting/
    ├── USR-003.md   # Report generation
    └── SYS-003.md   # Report engine

Advantages:

  • Groups related requirements
  • Mirrors feature structure
  • Good for feature-based development

Organize by Component

requirements/
├── config.toml
├── frontend/
│   ├── WEB-USR-001.md
│   ├── WEB-SYS-001.md
│   ├── MOBILE-USR-001.md
│   └── MOBILE-SYS-001.md
└── backend/
    ├── API-SYS-001.md
    ├── DB-SYS-001.md
    └── CACHE-SYS-001.md

Advantages:

  • Aligns with system architecture
  • Clear ownership boundaries
  • Natural for microservices

Note: Consider using namespaces in HRIDs (e.g., WEB-USR-001) to avoid conflicts.

Deep Hierarchies

Requiem supports arbitrary nesting:

requirements/
├── config.toml
└── product/
    ├── core/
    │   ├── auth/
    │   │   ├── USR-001.md
    │   │   └── SYS-001.md
    │   └── data/
    │       ├── USR-002.md
    │       └── SYS-002.md
    └── plugins/
        ├── export/
        │   └── USR-003.md
        └── import/
            └── USR-004.md

Caution: Deep hierarchies can be harder to navigate. Consider flat or shallow structures unless your project naturally requires depth.

Flat vs. Hierarchical

Flat Structure

requirements/
├── config.toml
├── USR-001.md
├── USR-002.md
├── ...
├── USR-050.md
├── SYS-001.md
├── SYS-002.md
├── ...
└── SYS-100.md

Advantages:

  • Simple and straightforward
  • Easy to understand
  • Works well for small/medium projects (< 100 requirements)

Disadvantages:

  • Directory listing can become unwieldy with many requirements
  • Harder to navigate in file browser with 100+ files

Best for: Small to medium projects, single-component systems.

Hierarchical Structure

requirements/
├── config.toml
├── user-requirements/
│   └── (50 files)
├── system-requirements/
│   └── (100 files)
└── test-requirements/
    └── (150 files)

Advantages:

  • Scalable to large projects (1000+ requirements)
  • Natural organization
  • Easier to navigate

Disadvantages:

  • Slightly more complex
  • Must decide on hierarchy scheme

Best for: Large projects, multi-component systems.

Best Practices

1. Start Flat, Refactor When Needed

Begin with a flat structure:

requirements/
├── config.toml
├── USR-001.md
└── SYS-001.md

Introduce subdirectories when you have 50+ requirements or natural groupings emerge.

2. Use Consistent Naming

If using subdirectories, name them consistently:

requirements/
├── 1-user-requirements/
├── 2-system-requirements/
├── 3-software-requirements/
└── 4-test-requirements/

Or:

requirements/
├── user/
├── system/
├── software/
└── test/

Avoid: Mixing naming schemes (user_reqs/, system-requirements/, Tests/).

3. Keep Shallow (2-3 Levels Max)

Prefer:

requirements/
└── user/
    └── USR-001.md

Over:

requirements/
└── level1/
    └── level2/
        └── level3/
            └── level4/
                └── USR-001.md

Deep hierarchies are hard to navigate and remember.

4. Align with Team Structure

Organize to match how your team works:

Team by feature:

requirements/
├── login-team/
├── payment-team/
└── reporting-team/

Team by layer:

requirements/
├── product-managers/  (USR requirements)
├── architects/        (SYS requirements)
└── developers/        (SWR requirements)

5. Don't Encode Information in Paths

Bad:

requirements/
└── high-priority/
    └── USR-001.md  # Priority encoded in directory

Good:

requirements/
└── USR-001.md

# USR-001.md content:
---
tags:
- high-priority
---
The requirement text...

Use tags or content for metadata, not directory structure. Directories are for organization only.

Special Cases

Mixed Content (Requirements + Documentation)

If requirements live alongside other documentation:

docs/
├── config.toml
├── introduction.md      ← Not a requirement
├── architecture.md      ← Not a requirement
├── requirements/
│   ├── USR-001.md      ← Requirement
│   └── SYS-001.md      ← Requirement
└── user-guide.md        ← Not a requirement

Set allow_unrecognised = true in config.toml to allow non-requirement markdown files.

Integration with MdBook

MdBook projects:

docs/
├── book.toml           ← MdBook config
├── src/
│   ├── SUMMARY.md      ← MdBook table of contents
│   ├── chapter1.md     ← Documentation
│   ├── USR-001.md      ← Requirement (can be in SUMMARY.md)
│   └── USR-002.md      ← Requirement
└── config.toml         ← Requiem config (allow_unrecognised = true)

See Integration > Using with MdBook for details.

Integration with Sphinx

Sphinx projects:

docs/
├── conf.py             ← Sphinx config
├── index.md
├── requirements/
│   ├── config.toml     ← Requiem config
│   ├── USR-001.md      ← Requirement
│   └── SYS-001.md      ← Requirement
└── other-content.md

See Integration > Using with Sphinx for details.

Monorepo Structure

Large monorepos with multiple products:

monorepo/
├── products/
│   ├── web-app/
│   │   └── requirements/
│   │       ├── config.toml
│   │       └── WEB-USR-001.md
│   └── mobile-app/
│       └── requirements/
│           ├── config.toml
│           └── MOBILE-USR-001.md
└── shared/
    └── requirements/
        ├── config.toml
        └── CORE-SYS-001.md

Each product/component has its own independent requirements directory with separate config.toml.

File System Considerations

Case Sensitivity

Linux/Mac: Filenames are case-sensitive

  • USR-001.md and usr-001.md are different files
  • Requiem only recognizes USR-001.md (uppercase HRID)

Windows: Filenames are case-insensitive

  • USR-001.md and usr-001.md refer to the same file
  • Use consistent casing to avoid issues

Recommendation: Always use uppercase HRIDs to avoid cross-platform issues.

Requiem follows symbolic links when scanning for requirements:

requirements/
├── current -> v2.0/     ← Symlink
├── v1.0/
│   └── USR-001.md
└── v2.0/
    └── USR-001.md

Caution: Ensure symlinks don't create cycles or duplicate requirements.

Hidden Files and Directories

Files and directories starting with . are typically ignored by Requiem (following standard Unix convention):

requirements/
├── .git/               ← Ignored
├── .DS_Store           ← Ignored (Mac)
├── config.toml
└── USR-001.md

Performance Considerations

Large Directories

Requiem uses parallel loading for performance:

requirements/
├── USR-001.md
├── USR-002.md
├── ...
└── USR-5000.md  # 5000 files loads quickly due to parallelism

Performance: Requiem can handle thousands of requirements efficiently. Directory structure has minimal performance impact.

Network File Systems

If requirements are on a network drive:

  • Initial loading may be slower
  • Consider using subdirectories to localize access patterns
  • Parallel loading helps mitigate network latency

Choosing Between Modes

When to Use Filename-Based Mode (Default)

Advantages:

  • Maximum flexibility - organize folders however you want
  • Easy to move files between folders without changing HRIDs
  • Works well with arbitrary organizational schemes (by feature, by team, etc.)
  • Explicit namespaces visible in every filename

Best for:

  • Projects where folder structure is organizational, not semantic
  • Teams that reorganize folders frequently
  • Mixed organizational schemes
  • When you want full control over namespaces

Example:

requirements/
├── team-a/
│   └── auth-USR-001.md      → HRID: auth-USR-001
└── team-b/
    └── auth-SYS-002.md      → HRID: auth-SYS-002

When to Use Path-Based Mode

Advantages:

  • Cleaner filenames (shorter, less redundant)
  • Folder structure enforces namespace consistency
  • Natural for hierarchical component structures
  • Automatic namespace creation from folders

Best for:

  • Projects with stable, hierarchical component structures
  • When folder structure mirrors system architecture
  • Microservices or multi-component systems
  • When you want enforced namespace-folder alignment

Example:

requirements/
├── auth/
│   ├── USR-001.md           → HRID: auth-USR-001
│   └── SYS-002.md           → HRID: auth-SYS-002
└── payment/
    ├── USR-001.md           → HRID: payment-USR-001
    └── SYS-002.md           → HRID: payment-SYS-002

Comparison Table

AspectFilename-BasedPath-Based
Filename containsFull HRIDKIND-ID only
Namespace fromFilenameFolder path
Folder flexibilityHighLow (tied to namespace)
File move impactNoneChanges HRID
Filename lengthLongerShorter
Default modeYesNo

Migration Between Modes

Converting from Filename-Based to Path-Based

  1. Update configuration:
# config.toml
_version = "1"
subfolders_are_namespaces = true
  1. Reorganize files to match namespace structure:
# Before (filename-based):
# requirements/
# ├── auth-USR-001.md
# └── payment-USR-002.md

# Create namespace folders
mkdir -p auth payment

# Move and rename files
mv auth-USR-001.md auth/USR-001.md
mv payment-USR-002.md payment/USR-002.md

# After (path-based):
# requirements/
# ├── auth/
# │   └── USR-001.md
# └── payment/
#     └── USR-002.md
  1. Verify:
req clean

Converting from Path-Based to Filename-Based

  1. Flatten files and encode namespace in filename:
# Before (path-based):
# requirements/
# ├── auth/
# │   └── USR-001.md        (HRID: auth-USR-001)
# └── payment/
#     └── USR-002.md        (HRID: payment-USR-002)

# Move and rename with full HRID
mv auth/USR-001.md auth-USR-001.md
mv payment/USR-002.md payment-USR-002.md

# Remove now-empty folders
rmdir auth payment

# After (filename-based):
# requirements/
# ├── auth-USR-001.md
# └── payment-USR-002.md
  1. Update configuration:
# config.toml
_version = "1"
subfolders_are_namespaces = false
  1. Verify:
req clean

Note: When converting between modes, the HRID (and thus UUID) remains the same, preserving all links and history.

Migration and Refactoring

Reorganizing Files

To reorganize directory structure in filename-based mode:

  1. Move requirement files:
mkdir system
mv SYS-*.md system/
  1. Verify:
req clean
  1. Commit:
git add -A
git commit -m "Organize system requirements into subdirectory"

Safe because: Requirements are identified by HRID (filename), not path. Moving files doesn't break links.

Splitting Directories

To split a large flat directory:

# Before
requirements/
├── USR-001.md (100 files)

# After
requirements/
├── user/
│   └── USR-001.md (100 files)
└── system/
    └── SYS-001.md (100 files)

Steps:

mkdir user system test
mv USR-*.md user/
mv SYS-*.md system/
mv TST-*.md test/
req clean  # Verify

Summary

Key Takeaways:

  1. Flexible: Flat or hierarchical, your choice
  2. Recursive: Subdirectories are automatically scanned
  3. Simple: Directory names don't affect requirement behavior
  4. Scalable: Supports small projects (10s) to large (1000s)
  5. Reorganizable: Safe to move files (links use UUIDs, not paths)

Recommendations:

  • Start flat, add structure as needed
  • Keep shallow (2-3 levels max)
  • Organize by kind, feature, or component
  • Use consistent naming conventions
  • Align with team structure

Next Steps

Namespaces

Namespaces extend HRIDs with prefixes to organize requirements in large, multi-component projects. This chapter explains when and how to use them.

What Are Namespaces?

A namespace is an optional prefix in an HRID that provides additional context:

USR-001              # No namespace
AUTH-USR-001         # One namespace level: AUTH
AUTH-LOGIN-USR-001   # Two namespace levels: AUTH, LOGIN
A-B-C-USR-001        # Three namespace levels: A, B, C

HRID Format with Namespaces

Complete format:

{NAMESPACE-}*{KIND}-{ID}

Where:

  • NAMESPACE: Zero or more namespace segments
  • KIND: Requirement kind (e.g., USR, SYS)
  • ID: Numeric identifier

Examples:

USR-001                    # KIND=USR, ID=001, namespace=[]
COMPONENT-USR-001          # KIND=USR, ID=001, namespace=[COMPONENT]
AUTH-LOGIN-SYS-042         # KIND=SYS, ID=042, namespace=[AUTH, LOGIN]

When to Use Namespaces

Large Projects

Projects with many requirements benefit from namespacing:

# Without namespaces (confusion)
USR-001  # Which component?
USR-002  # Auth or payment?
USR-003  # Mobile or web?

# With namespaces (clarity)
AUTH-USR-001    # Authentication user requirement
PAY-USR-002     # Payment user requirement
MOBILE-USR-003  # Mobile app user requirement

Multi-Component Systems

Systems with distinct components or subsystems:

FRONTEND-USR-001
FRONTEND-SYS-001

BACKEND-USR-001
BACKEND-SYS-001

DATABASE-SYS-001
CACHE-SYS-001

Product Families

Related products sharing requirements:

CORE-USR-001      # Shared across all products
CORE-SYS-001

MOBILE-USR-001    # Mobile-specific
MOBILE-SYS-001

WEB-USR-001       # Web-specific
WEB-SYS-001

Team Boundaries

Map namespaces to team ownership:

TEAM-ALPHA-USR-001    # Team Alpha's requirements
TEAM-BETA-USR-001     # Team Beta's requirements
SHARED-USR-001        # Cross-team requirements

Acquisitions and Mergers

Integrate acquired codebases without renumbering:

LEGACY-USR-001    # From acquired company (existing numbering)
NEW-USR-001       # Newly created requirements

When NOT to Use Namespaces

Small Projects

Projects with < 100 requirements rarely need namespaces:

# Simple project (no namespace needed)
USR-001
USR-002
SYS-001
SYS-002

Namespaces add complexity without benefit for small projects.

Single Component

If your project is a single cohesive unit:

# Single-component app
USR-001
SYS-001
TST-001

No need for namespaces unless planning for future growth.

Shallow Hierarchy

If requirements naturally form a flat or shallow structure, namespaces may be overkill.

Namespace Strategies

Strategy 1: By Component

Organize by system architecture:

AUTH-USR-001       # Authentication component
AUTH-SYS-001

API-USR-001        # API gateway
API-SYS-001

DB-SYS-001         # Database layer

CACHE-SYS-001      # Cache layer

Advantages:

  • Mirrors system architecture
  • Clear component ownership
  • Natural for microservices

When to use: Systems with well-defined component boundaries.

Strategy 2: By Layer

Organize by architectural layer:

UI-USR-001         # User interface layer
UI-SYS-001

BL-SYS-001         # Business logic layer

DATA-SYS-001       # Data layer

Advantages:

  • Aligns with layered architectures
  • Clear layer separation

When to use: Traditional n-tier applications.

Strategy 3: By Feature

Organize by product feature:

LOGIN-USR-001      # Login feature
LOGIN-SYS-001
LOGIN-TST-001

PAYMENT-USR-001    # Payment feature
PAYMENT-SYS-001
PAYMENT-TST-001

REPORTING-USR-001  # Reporting feature
REPORTING-SYS-001

Advantages:

  • Groups related requirements
  • Feature-based development
  • Easy feature scoping

When to use: Feature-driven development, agile teams.

Strategy 4: Hybrid

Combine multiple levels:

MOBILE-AUTH-USR-001    # Mobile app, auth feature, user requirement
MOBILE-PAY-SYS-001     # Mobile app, payment feature, system requirement

WEB-AUTH-USR-001       # Web app, auth feature, user requirement
WEB-PAY-SYS-001        # Web app, payment feature, system requirement

Advantages:

  • Maximum organization
  • Clear context at a glance

When to use: Very large, multi-product systems.

Caution: Deep hierarchies can make HRIDs verbose. Balance clarity with brevity.

Namespace Depth

Single Level

COMPONENT-USR-001

Typical: 5-10 namespaces per project

Best for: Medium projects with distinct components

Two Levels

PRODUCT-COMPONENT-USR-001

Typical: 3-5 top-level namespaces, 3-7 sub-namespaces each

Best for: Large projects, product families

Three+ Levels

ORG-PRODUCT-COMPONENT-USR-001

Typical: Very large enterprises

Best for: Massive systems, multi-organization projects

Caution: HRIDs become long and unwieldy. Consider if truly necessary.

Namespace Naming Conventions

Use Descriptive Names

# Good
AUTH-USR-001      # Clear: authentication
PAYMENT-SYS-001   # Clear: payment processing

# Less clear
A-USR-001         # What is "A"?
MOD1-SYS-001      # What is "MOD1"?

Keep Short

# Good
AUTH-USR-001      # 4 characters
PAY-USR-001       # 3 characters

# Too long
AUTHENTICATION-USR-001    # 14 characters
PAYMENT-PROCESSING-USR-001  # 18 characters

Aim for 3-8 characters per namespace segment.

Use Consistent Casing

# Good (all uppercase)
AUTH-USR-001
PAYMENT-SYS-001

# Inconsistent (avoid)
auth-USR-001
Payment-SYS-001

Convention: Use uppercase to match KIND and ID conventions.

Avoid Special Characters

# Good
AUTH-USR-001
PAYMENT-SYS-001

# Bad (don't use)
AUTH_USR-001      # Underscore confuses parsing
AUTH.USR.001      # Periods not supported
AUTH/USR/001      # Slashes not supported

Only use hyphens as separators.

Implementation

Creating Namespaced Requirements

Use the namespace in the KIND argument:

# Single namespace
req add AUTH-USR

# Output: Added requirement AUTH-USR-001
# Two namespace levels
req add MOBILE-AUTH-SYS

# Output: Added requirement MOBILE-AUTH-SYS-001

Linking Namespaced Requirements

Linking works identically:

req link MOBILE-AUTH-SYS-001 AUTH-USR-001

Namespaces don't affect link functionality.

File Naming

Filenames match HRIDs exactly:

requirements/
├── AUTH-USR-001.md
├── AUTH-SYS-001.md
├── PAYMENT-USR-001.md
└── MOBILE-AUTH-USR-001.md

Namespace Organization with Directories

Combine namespaces with directory structure:

Option 1: Match Namespace to Directory

requirements/
├── auth/
│   ├── AUTH-USR-001.md
│   └── AUTH-SYS-001.md
└── payment/
    ├── PAYMENT-USR-001.md
    └── PAYMENT-SYS-001.md

Advantages:

  • Reinforces namespace structure
  • Easy to navigate

Disadvantage:

  • Redundancy (namespace in filename and path)

Option 2: Namespace Without Matching Directory

requirements/
├── AUTH-USR-001.md
├── AUTH-SYS-001.md
├── PAYMENT-USR-001.md
└── PAYMENT-SYS-001.md

Advantages:

  • Simpler structure
  • No redundancy

Disadvantage:

  • Large directories if many components

Option 3: Hybrid

requirements/
├── mobile/
│   ├── MOBILE-AUTH-USR-001.md
│   └── MOBILE-PAY-USR-001.md
└── web/
    ├── WEB-AUTH-USR-001.md
    └── WEB-PAY-USR-001.md

Advantages:

  • Top level organized by directory
  • Sub-level by namespace

Configuration

Restricting Namespaces

Currently, Requiem doesn't restrict namespaces via configuration. Any valid namespace is accepted.

Workaround: Use allowed_kinds to restrict full namespaced kinds:

_version = "1"
allowed_kinds = [
    "AUTH-USR",
    "AUTH-SYS",
    "PAYMENT-USR",
    "PAYMENT-SYS",
]

This allows:

  • AUTH-USR-001
  • PAYMENT-SYS-001

This blocks:

  • INVALID-USR-001
  • USR-001 ✗ (no namespace)

Limitation: Doesn't enforce namespace structure for multi-level namespaces.

Future Configuration

Planned configuration options (not yet implemented):

# Planned (not implemented)
[namespaces]
required = true          # Require all HRIDs to have namespaces
allowed = ["AUTH", "PAYMENT", "REPORTING"]
separator = "-"          # Customize separator (default: "-")
max_depth = 2            # Limit namespace depth

Migration to Namespaces

Adding Namespaces to Existing Project

Challenge: Existing requirements lack namespaces:

USR-001.md
USR-002.md
SYS-001.md

Goal: Add namespaces:

AUTH-USR-001.md
PAYMENT-USR-002.md
AUTH-SYS-001.md

Steps:

  1. Plan namespace scheme: Decide which requirements belong to which namespace

  2. Rename files:

mv USR-001.md AUTH-USR-001.md
mv USR-002.md PAYMENT-USR-002.md
mv SYS-001.md AUTH-SYS-001.md
  1. Update HRIDs in frontmatter: Edit each file to update the HRID references

  2. Fix parent links: Run req clean to correct parent HRIDs

req clean
  1. Verify:
req clean  # Should succeed with no errors
  1. Commit:
git add -A
git commit -m "Add namespaces to requirements"

Note: UUIDs remain unchanged, so relationships are preserved.

Examples

Example 1: E-commerce Platform

# Customer-facing requirements
CUSTOMER-USR-001.md  # Customer account management
CUSTOMER-USR-002.md  # Product browsing

# Cart and checkout
CART-USR-001.md      # Shopping cart
CHECKOUT-USR-001.md  # Checkout process

# Payment processing
PAYMENT-SYS-001.md   # Payment gateway integration
PAYMENT-SYS-002.md   # PCI compliance

# Order management
ORDER-SYS-001.md     # Order processing
ORDER-SYS-002.md     # Order fulfillment

# Inventory
INVENTORY-SYS-001.md # Stock management

Example 2: Aerospace System

# Aircraft levels (DO-178C)
AIRCRAFT-URQT-001.md   # Aircraft-level user requirement

# System level
AVIONICS-SRQT-001.md   # Avionics system requirement
ENGINES-SRQT-001.md    # Engine system requirement

# Software level
AVIONICS-FCS-SWRQT-001.md   # Flight control software
AVIONICS-NAV-SWRQT-001.md   # Navigation software

# Hardware level
AVIONICS-FCS-HWRQT-001.md   # Flight control hardware

Example 3: Mobile and Web Apps

# Shared requirements
CORE-USR-001.md         # Cross-platform user requirement
CORE-SYS-001.md         # Backend API

# Mobile-specific
MOBILE-IOS-USR-001.md   # iOS-specific requirement
MOBILE-ANDROID-USR-001.md  # Android-specific

# Web-specific
WEB-USR-001.md          # Web app requirement
WEB-ADMIN-USR-001.md    # Admin panel requirement

Best Practices

1. Design Namespace Scheme Early

Define your namespace strategy before creating many requirements:

# Document in config.toml comments
_version = "1"

# Namespace scheme:
# - AUTH: Authentication and authorization
# - PAYMENT: Payment processing
# - REPORTING: Report generation
# - ADMIN: Administration features

allowed_kinds = ["AUTH-USR", "AUTH-SYS", "PAYMENT-USR", "PAYMENT-SYS"]

2. Keep Namespaces Shallow

Prefer 1-2 levels over 3+:

# Good
AUTH-USR-001

# Still good
MOBILE-AUTH-USR-001

# Getting long
COMPANY-PRODUCT-MOBILE-AUTH-USR-001

3. Document Namespace Meanings

Create a README or documentation page:

# Namespace Guide

- **AUTH**: Authentication and authorization
- **PAYMENT**: Payment processing
- **REPORT**: Report generation
- **ADMIN**: Administration and configuration

4. Consistent Abbreviations

Use consistent abbreviations across namespaces:

# Good (consistent)
AUTH-USR-001
AUTH-SYS-001
PAYMENT-USR-001
PAYMENT-SYS-001

# Inconsistent (avoid)
AUTH-USR-001
AUTHENTICATION-SYS-001
PAY-USR-001
PAYMENT_PROCESSING-SYS-001

5. Consider Future Growth

Choose namespaces that won't become obsolete:

# Flexible
MOBILE-USR-001       # Can add MOBILE-IOS, MOBILE-ANDROID later

# Inflexible
IPHONE-USR-001       # What about iPads? Android?

Summary

Key Takeaways:

  1. Optional: Namespaces are optional; use when beneficial
  2. Hierarchical: Support multiple levels (1-3 typical)
  3. Flexible: Choose strategy that fits your project
  4. Scalable: Essential for large, multi-component systems
  5. Format: {NAMESPACE-}*{KIND}-{ID}

When to use:

  • Large projects (> 100 requirements)
  • Multi-component systems
  • Product families
  • Team boundaries
  • Acquisitions

When NOT to use:

  • Small projects (< 100 requirements)
  • Single-component systems
  • When simplicity is priority

Best practices:

  • Design namespace scheme early
  • Keep shallow (1-2 levels)
  • Use descriptive, short names
  • Document namespace meanings
  • Consider future growth

Next Steps

Maintaining Requirements

Requirements evolve throughout a project's lifecycle. This chapter covers maintenance tasks that keep your requirements accurate and consistent.

Overview

Requiem provides tools for:

Common Maintenance Tasks

Regular Cleanup

Run req clean periodically to ensure consistency:

req clean

This command:

  • Loads all requirements
  • Validates frontmatter and format
  • Corrects parent HRIDs if requirements were renamed
  • Reports any errors or inconsistencies

Frequency: Run after major reorganizations or before releases.

After Renaming Requirements

If you rename requirement files (change HRIDs):

  1. Rename the file:
mv USR-001.md USR-100.md
  1. Update parent references:
req clean
  1. Verify changes:
git diff

The clean command updates all parent HRIDs automatically.

After Editing Content

When requirement text changes:

  1. Edit the markdown body
  2. Save the file
  3. Commit with a descriptive message:
git add USR-001.md
git commit -m "Update USR-001: clarify email validation requirement"

The fingerprint updates automatically when content changes, enabling change detection.

Managing Requirements at Scale

For projects with hundreds of requirements:

Use scripts: Automate repetitive tasks

# Example: Add a tag to all USR requirements
for file in USR-*.md; do
    # Add tag via sed or Python script
done

Use version control: Track changes over time

# See what requirements changed this sprint
git log --since="2 weeks ago" --name-only -- "*.md"

Use traceability: Understand impact of changes

# Find all children of a requirement
grep -r "uuid: <parent-uuid>" *.md

Maintenance Best Practices

1. Validate Before Committing

Always run req clean before committing changes:

req clean && git add -A && git commit -m "Update requirements"

This catches errors before they enter the repository.

2. Use Descriptive Commit Messages

Bad:

git commit -m "Update reqs"

Good:

git commit -m "Add USR-042: user data export requirement

Related to feature request #123. Establishes requirements
for CSV and JSON export formats."

3. Review Changes Carefully

Before committing requirement changes, review diffs:

git diff USR-001.md

Ensure:

  • UUID hasn't changed (breaking traceability)
  • Metadata is valid
  • Content changes are intentional

4. Keep Requirements Current

Regular reviews: Schedule periodic requirement reviews

Update as needed: Don't let requirements become stale documentation

Archive obsolete requirements: Move to archived/ subdirectory rather than deleting

5. Document Maintenance Procedures

Create a CONTRIBUTING.md or similar:

# Requirements Maintenance

## Before Committing
1. Run `req clean`
2. Review diffs carefully
3. Don't modify UUIDs manually

## Renaming Requirements
1. Rename file
2. Run `req clean` to update parent references
3. Commit changes

## Adding Tags
Use YAML syntax in frontmatter...

Tools and Automation

Pre-commit Hooks

Automate validation with Git hooks:

#!/bin/bash
# .git/hooks/pre-commit

echo "Validating requirements..."
req clean

if [ $? -ne 0 ]; then
    echo "Error: Requirements validation failed"
    exit 1
fi

CI/CD Integration

Add requirement validation to CI:

# .github/workflows/requirements.yml
name: Validate Requirements

on: [push, pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install Requiem
        run: cargo install requirements-manager
      - name: Validate requirements
        run: req clean
        working-directory: ./requirements

Scripts for Common Tasks

Find requirements without tests:

#!/bin/bash
# List USR requirements not linked by any TST requirement
comm -23 \
  <(ls USR-*.md | sed 's/.md//' | sort) \
  <(grep -oh "USR-[0-9]*" TST-*.md | sort -u)

Generate traceability report:

#!/bin/bash
# Show parent-child relationships
for file in *.md; do
    hrid=$(basename "$file" .md)
    parents=$(grep "hrid:" "$file" | awk '{print $2}')
    if [ -n "$parents" ]; then
        echo "$hrid -> $parents"
    fi
done

Error Recovery

Corrupted Frontmatter

If YAML becomes invalid:

  1. Check syntax:
req clean  # Reports specific error
  1. Fix manually or restore from Git:
git checkout HEAD -- USR-001.md
  1. Use online YAML validator if needed

Duplicate UUIDs

If two requirements have the same UUID (serious error):

  1. Requiem will panic with error message
  2. Identify files with duplicate UUIDs
  3. Manually assign new UUID to one:
uuidgen  # Generate new UUID
# Edit file, replace UUID
  1. Verify:
req clean

Missing Parents

If a parent requirement is deleted but children still reference it:

  1. Requiem reports error during req clean
  2. Options:
    • Restore deleted parent
    • Remove parent reference from child
    • Link child to different parent

Merge Conflicts

When merging Git branches with requirement changes:

  1. Resolve conflicts in frontmatter carefully:

    • UUIDs should never conflict (unique per requirement)
    • Timestamps: keep newer
    • Parents: merge both sets if both added parents
  2. Resolve markdown body conflicts normally

  3. After resolving:

req clean  # Validate merged result

Monitoring and Reporting

Requirement Statistics

Count requirements by kind:

ls USR-*.md | wc -l  # User requirements
ls SYS-*.md | wc -l  # System requirements

Change Tracking

Requirements changed in last month:

git log --since="1 month ago" --name-only --pretty=format: -- "*.md" | \
  sort -u | grep -E "^[A-Z]+-[0-9]+\.md$"

Coverage Analysis

Find requirements without children (potential gaps):

# Find USR requirements not referenced by any SYS requirement
comm -23 \
  <(ls USR-*.md | sed 's/.md//' | sort) \
  <(grep -roh "USR-[0-9]*" SYS-*.md | sort -u)

Next Steps

Dive deeper into specific maintenance topics:

Correcting HRIDs

The req clean command corrects outdated parent HRIDs in requirement files. This chapter explains when and how to use it.

The Problem

Requirements reference their parents using HRIDs for human readability:

parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001  # Human-readable reference

If you rename the parent file (USR-001.mdUSR-100.md), the HRID in child requirements becomes outdated:

# Child still says:
parents:
- hrid: USR-001  # Wrong! File is now USR-100.md

The UUID remains correct (traceability is preserved), but the HRID shown to humans is misleading.

The Solution: req clean

The req clean command:

  1. Loads all requirements
  2. For each requirement, checks parent HRIDs against actual parent files
  3. Corrects any mismatches
  4. Saves updated requirements

Basic Usage

req clean

Run in your requirements directory. No output means success (all HRIDs were correct or have been fixed).

With Custom Root

req --root /path/to/requirements clean

Specify a different requirements directory.

Verbose Output

req -v clean

Shows what's being corrected:

INFO Corrected parent HRID in SYS-001: USR-001 → USR-100
INFO Corrected parent HRID in SYS-002: USR-001 → USR-100

When to Run req clean

After Renaming Requirements

Scenario: You renamed a requirement file.

Steps:

  1. Rename the file:
mv USR-001.md USR-100.md
  1. Correct parent references:
req clean
  1. Verify changes:
git diff

You'll see parent HRIDs updated in child requirements.

After Reorganization

Scenario: Major restructuring with many renamed files.

Steps:

  1. Perform renames:
mv USR-001.md AUTH-USR-001.md
mv USR-002.md PAYMENT-USR-002.md
# ... many more
  1. Fix all references at once:
req clean
  1. Verify:
git status    # See all modified files
git diff      # Review changes

Before Committing

Best practice: Run req clean before every commit involving requirement changes.

req clean && git add -A && git commit -m "Reorganize requirements"

This ensures the repository always has correct HRIDs.

Regular Maintenance

Frequency: Run periodically (e.g., before releases) to catch any drift.

req clean

If requirements are managed carefully, this should show no changes.

How It Works

Step 1: Load All Requirements

Requiem scans the requirements directory recursively, loading all .md files with valid HRID names.

Step 2: Build Index

Creates a UUID-to-requirement mapping:

UUID 4bfeb7d5-... → USR-100 (actual current HRID)
UUID 3fc6800c-... → SYS-001
...

Step 3: Check Each Parent Reference

For each requirement, examines parent references:

# Child requirement SYS-001.md
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  hrid: USR-001  # Check if this matches actual HRID for this UUID

Step 4: Correct Mismatches

If the HRID doesn't match:

  • Look up the UUID in the index
  • Find the actual current HRID
  • Update the parent reference
  • Save the requirement file

Step 5: Report Results

With verbose logging (-v), reports each correction. Otherwise, silent success.

Examples

Example 1: Simple Rename

Before:

requirements/
├── USR-001.md
└── SYS-001.md

SYS-001.md links to USR-001:

# SYS-001.md
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  hrid: USR-001

Rename parent:

mv USR-001.md USR-100.md

Run clean:

req clean

After:

SYS-001.md now shows correct HRID:

# SYS-001.md
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  hrid: USR-100  # Corrected!

Example 2: Multiple Children

Scenario: One parent with multiple children.

Before:

requirements/
├── USR-001.md
├── SYS-001.md  (parent: USR-001)
├── SYS-002.md  (parent: USR-001)
└── SYS-003.md  (parent: USR-001)

Rename parent:

mv USR-001.md USR-050.md

Run clean:

req -v clean

Output:

INFO Corrected parent HRID in SYS-001: USR-001 → USR-050
INFO Corrected parent HRID in SYS-002: USR-001 → USR-050
INFO Corrected parent HRID in SYS-003: USR-001 → USR-050

All three children are updated in one command.

Example 3: Adding Namespaces

Scenario: Migrating to namespaced HRIDs.

Before:

requirements/
├── USR-001.md
├── USR-002.md
├── SYS-001.md  (parent: USR-001)
└── SYS-002.md  (parent: USR-002)

Rename with namespaces:

mv USR-001.md AUTH-USR-001.md
mv USR-002.md PAYMENT-USR-002.md
mv SYS-001.md AUTH-SYS-001.md
mv SYS-002.md PAYMENT-SYS-002.md

Run clean:

req clean

Result: All parent references updated to namespaced HRIDs.

Edge Cases

Requirement Not Found

Scenario: Child references a parent UUID that doesn't exist.

Example:

# SYS-001.md
parents:
- uuid: 00000000-0000-0000-0000-000000000000  # No requirement with this UUID
  hrid: USR-999

Behavior: req clean panics with error message:

Error: Parent requirement 00000000-0000-0000-0000-000000000000 not found!

Resolution:

  • Restore the missing parent requirement, or
  • Manually remove the invalid parent reference from the child

Self-Referential Parent

Scenario: Requirement lists itself as a parent (should never happen).

Example:

# SYS-001.md
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a  # Same as own UUID!
  hrid: SYS-001

Behavior: req clean panics with error message:

Error: Requirement 4bfeb7d5-... is its own parent!

Resolution: Manually remove the self-reference from the frontmatter.

Circular Dependencies

Scenario: Requirement A depends on B, B depends on C, C depends on A.

Current behavior: req clean doesn't detect cycles (cycle detection is planned but not implemented).

Impact: HRIDs will be corrected, but the circular dependency remains undetected.

Workaround: Manually audit requirement relationships or use external tools.

Integration with Workflows

Pre-commit Hook

Automatically correct HRIDs before every commit:

#!/bin/bash
# .git/hooks/pre-commit

echo "Correcting requirement HRIDs..."
req clean

if [ $? -ne 0 ]; then
    echo "Error: Failed to correct HRIDs"
    exit 1
fi

# Stage any changes made by req clean
git add -u

Benefit: Never commit incorrect HRIDs.

Caution: Automatically stages changes. Review carefully.

CI Pipeline

Validate HRIDs in CI:

# .github/workflows/requirements.yml
- name: Validate HRIDs
  run: |
    req clean
    if [ -n "$(git status --porcelain)" ]; then
      echo "Error: HRIDs are out of sync"
      git diff
      exit 1
    fi

Benefit: Catches incorrect HRIDs before merging.

Manual Review Workflow

For critical projects, manually review HRID corrections:

# Run clean
req clean

# Review changes
git diff

# If acceptable, commit
git add -A
git commit -m "Correct parent HRIDs after reorganization"

Performance

req clean loads all requirements in parallel, making it fast even for large projects:

  • 100 requirements: < 1 second
  • 1000 requirements: ~2-3 seconds
  • 10000 requirements: ~15-20 seconds

Scales well due to Rust's performance and parallel processing.

Limitations

No Dry-Run Mode

Currently, req clean modifies files immediately. There's no preview mode.

Workaround: Use Git to preview changes:

req clean         # Make changes
git diff          # Preview
git checkout -- . # Undo if needed (before committing)

No Selective Correction

Can't correct only specific requirements; it's all-or-nothing.

Workaround: Use Git to selectively stage changes:

req clean
git add SYS-001.md SYS-002.md  # Stage only specific files

Requires All Parents Present

If a parent requirement is missing, req clean fails. Can't correct partial sets.

Workaround: Ensure all requirements are present, or manually fix references.

Best Practices

1. Run Before Committing

req clean && git add -A && git commit

Make it a habit.

2. Review Changes

Always review what req clean changed:

req clean
git diff  # See what was corrected

3. Use Verbose Mode for Learning

When first using req clean, run with -v to understand what it's doing:

req -v clean

4. Combine with Validation

Use req clean as a validation step:

req clean
if [ $? -eq 0 ]; then
    echo "Requirements are consistent"
else
    echo "Errors found"
fi

5. Document in Team Processes

Include in your team's documentation:

## Renaming Requirements

1. Rename the file
2. Run `req clean`
3. Review changes with `git diff`
4. Commit

Troubleshooting

Command Not Found

Error: req: command not found

Solution: Install Requiem:

cargo install requirements-manager

Permission Denied

Error: Error: Permission denied

Solution: Ensure you have write permissions to requirement files.

Configuration Parse Error

Error: Error: Failed to parse config file

Solution: Check config.toml syntax. Remove or fix if invalid.

Unexpected Changes

Issue: req clean makes unexpected modifications.

Diagnosis:

  1. Run with verbose: req -v clean
  2. Examine which HRIDs are being corrected
  3. Check if requirement files were renamed

Resolution: Review changes with git diff. Revert if incorrect.

Summary

Key points:

  • Purpose: Correct outdated parent HRIDs after renaming requirements
  • Usage: req clean in requirements directory
  • When: After renaming files, before committing, regular maintenance
  • How: Loads all requirements, checks parent HRIDs, corrects mismatches
  • Safe: Uses UUIDs for correctness; HRIDs are display-only

Best practice: Run req clean before every commit involving requirements.

Limitation: No dry-run or selective correction (yet).

Next Steps

Fingerprints and Change Detection

Requiem uses content fingerprints to detect when requirements change. This chapter explains how fingerprints work and enable change management.

What is a Fingerprint?

A fingerprint is a cryptographic hash (SHA256) of a requirement's semantic content. It's stored in parent references:

# SYS-001.md
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001

The fingerprint represents the state of USR-001 when SYS-001 was last reviewed or updated.

How Fingerprints Work

Creation

When you link a child to a parent:

req link SYS-001 USR-001

Requiem:

  1. Computes the fingerprint of USR-001's content
  2. Stores it in SYS-001's parent reference

Updates

Fingerprints update in two scenarios:

1. When creating the link:

req link SYS-001 USR-001
# Fingerprint captured at link time

2. When the parent's content changes:

  • The parent's fingerprint is recomputed automatically
  • Child references keep the OLD fingerprint
  • This creates a mismatch, indicating the child may need review

What's Included in the Fingerprint

Fingerprints hash:

  • Markdown body: The requirement text
  • Tags: Any tags in the frontmatter

Fingerprints do NOT include:

  • ✗ HRID (just a label)
  • ✗ UUID (stable identifier, not content)
  • ✗ Created timestamp (metadata, not content)
  • ✗ Parent relationships (separate from content)

Example

Requirement USR-001:

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
tags:
- authentication
- security
---

The system shall validate user email addresses according to RFC 5322.

Fingerprint computation:

Content: "The system shall validate user email addresses according to RFC 5322."
Tags: ["authentication", "security"]
→ Encode with Borsh
→ Hash with SHA256
→ Fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda

Use Cases

Change Detection

Problem: A parent requirement changes. Which child requirements are affected?

Solution: Compare fingerprints.

Example:

  1. Initial state:
# SYS-001.md links to USR-001
parents:
- uuid: 4bfeb7d5-...
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001
  1. Someone edits USR-001:
# USR-001.md
The system shall validate user email addresses according to RFC 5322.
Email validation must occur before account creation.  # ← New sentence
  1. USR-001's fingerprint changes:
New fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  1. SYS-001 still has the old fingerprint:
# SYS-001.md
parents:
- fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda  # Old!
  1. Mismatch detected: SYS-001 needs review because its parent changed.

Impact Analysis

Question: If I change this requirement, what else is affected?

Answer: Use the req suspect command after making changes to find affected children.

Workflow:

# 1. Edit a parent requirement
vim USR-001.md  # Make your changes

# 2. Check for suspect links
req suspect
# Output shows all affected children:
#   SYS-001 → USR-001
#   SYS-002 → USR-001
#   ... (fingerprint mismatches)

# 3. Review each affected child
vim SYS-001.md
vim SYS-002.md

# 4. Accept fingerprints after review
req accept SYS-001 USR-001
req accept SYS-002 USR-001

# Or accept all at once
req accept --all

Manual process (if needed):

# 1. Get UUID of the requirement you're changing
grep "uuid:" USR-001.md

# 2. Find all requirements that reference this UUID
grep -r "uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a" *.md

# 3. Those requirements may need review after your change

Review Tracking

Goal: Track which requirements need review after upstream changes.

Current state: Basic suspect link detection implemented via req suspect and req accept commands.

Available now:

  • Detect fingerprint mismatches with req suspect
  • Accept individual links with req accept <child> <parent>
  • Accept all suspect links with req accept --all
  • CI/CD integration via exit codes

Future: Advanced review workflows with status tracking and assignments (planned feature).

Computing Fingerprints

Viewing a Requirement's Fingerprint

No built-in command yet, but you can compute it manually:

Option 1: Link to a temporary requirement

# Create temp requirement
req add TEMP
# Link to target
req link TEMP-001 USR-001
# View fingerprint in TEMP-001.md
grep "fingerprint:" TEMP-001.md
# Clean up
rm TEMP-001.md

Option 2: Use Rust/Python script

Not currently exposed via CLI. Requires custom scripting.

Comparing Fingerprints

Problem: Is my child requirement's parent reference current?

Solution: Use the req suspect command:

req suspect

This automatically:

  1. Loads all requirements
  2. Compares stored parent fingerprints with current parent fingerprints
  3. Lists all mismatched fingerprints (suspect links)

Example output:

Found 2 suspect link(s):

  SYS-001 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

  SYS-002 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

If no suspect links exist:

No suspect links found.

Exit codes:

  • 0: All fingerprints current
  • 1: Suspect links found (useful for CI/CD)

Manual process (if needed):

  1. Find parent UUID and stored fingerprint in child:
# SYS-001.md
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  1. Compute current fingerprint of parent (see above)

  2. Compare:

    • Match: Child is current
    • Mismatch: Child needs review

What Changes Affect Fingerprints

Changes that Update Fingerprints

Editing requirement text:

# Before
The system shall validate emails.

# After
The system shall validate emails according to RFC 5322.

→ Fingerprint changes

Adding/removing tags:

# Before
tags:
- authentication

# After
tags:
- authentication
- security

→ Fingerprint changes

Modifying tags:

# Before
tags:
- high-priority

# After
tags:
- medium-priority

→ Fingerprint changes

Whitespace changes in content:

# Before
The system shall validate emails.

# After
The system shall validate emails.

→ Fingerprint changes (trailing whitespace added)

Changes that DON'T Affect Fingerprints

Renaming the requirement:

mv USR-001.md USR-100.md

→ Fingerprint unchanged (HRID is not part of content)

Changing UUID (don't do this!):

# Before
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a

# After
uuid: 00000000-0000-0000-0000-000000000000

→ Fingerprint unchanged (but breaks traceability!)

Changing created timestamp:

# Before
created: 2025-07-22T12:19:56Z

# After
created: 2025-08-01T10:00:00Z

→ Fingerprint unchanged

Adding/removing parents:

# Before
parents:
- uuid: ...

# After
parents:
- uuid: ...
- uuid: ...  # Added parent

→ Fingerprint unchanged

Fingerprint Algorithms

Current Algorithm

Encoding: Borsh (Binary Object Representation Serializer for Hashing)

  • Deterministic serialization
  • Consistent across platforms
  • Efficient for hashing

Hashing: SHA256

  • Cryptographically secure
  • 256-bit output (64 hex characters)
  • Collision resistant

Process:

1. Collect content and tags
2. Serialize with Borsh: content + tags → binary
3. Hash with SHA256: binary → 256-bit hash
4. Encode as hex: hash → 64-character string

Why These Choices?

Borsh:

  • Stable encoding (no ambiguity)
  • Handles strings and collections consistently
  • Designed for hashing use cases

SHA256:

  • Industry standard
  • Strong collision resistance
  • Fast to compute

Benefits:

  • Consistent fingerprints across systems
  • Detects even small changes
  • Impossible to forge (cryptographically secure)

Practical Examples

Example 1: Detecting Stale References

Scenario: USR-001 was updated 2 months ago. Are any child requirements out of date?

Process:

# Check for suspect links
req suspect

Output:

Found 1 suspect link(s):

  SYS-001 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

Result: SYS-001 has a stale fingerprint and needs review.

Next steps:

# Review changes
vim USR-001.md  # See what changed
vim SYS-001.md  # Update if needed

# Accept the link
req accept SYS-001 USR-001

# Verify clean
req suspect
# Output: No suspect links found.

Example 2: Tag Changes

Scenario: Add a tag to a requirement.

Before:

# USR-001.md
tags:
- authentication

Fingerprint: e533784f...

After:

# USR-001.md
tags:
- authentication
- security

Fingerprint: c4020419... (changed!)

Impact: Any child requirements now have stale fingerprints.

Example 3: Whitespace-Only Changes

Scenario: Reformatting requirement text.

Before:

The system shall validate emails.

After:

The system shall validate emails.

(Added blank line)

Result: Fingerprint changes!

Caution: Even whitespace affects fingerprints. Be mindful of formatting changes.

Limitations and Future Work

Implemented Features

✓ Automatic suspect link detection

Use req suspect to find all stale fingerprints:

req suspect
# Lists all requirements with fingerprint mismatches

✓ Accepting suspect links

Update fingerprints after review:

# Accept individual link
req accept SYS-001 USR-001

# Accept all suspect links
req accept --all

✓ CI/CD integration

Exit codes enable automation:

req suspect
# Exit 0 if clean, exit 1 if suspect links found

Current Limitations

1. No review state tracking

No tracking of review status (current, under review, approved).

Planned: Review state management with status tracking and assignments.

2. No reporting

Can't generate comprehensive reports of requirement status.

Planned: req report command for traceability and review status.

3. No impact visualization

Can't see full dependency tree affected by a change.

Planned: req impact USR-001 to show affected descendants.

4. No fingerprint diff

Can't see what content changed between fingerprints.

Planned: req diff USR-001 to show fingerprint changes and content diff.

5. Whitespace sensitivity

Formatting changes trigger fingerprint updates.

Trade-off: Precision vs. false positives. Current design prioritizes detecting all changes.

Planned Features

Review state management:

req review start SYS-001
# Mark SYS-001 as "under review"

req review complete SYS-001
# Mark as "reviewed" and update fingerprints

req status
# Output:
# USR-001: current
# SYS-001: reviewed (parents unchanged since review)
# SYS-002: needs review (parent changed)

Impact analysis:

req impact USR-001
# Output:
# Direct children:
#   SYS-001, SYS-002
# Indirect descendants:
#   SWR-001 (via SYS-001)
#   TST-001 (via SWR-001)
# Total affected: 4 requirements

Reporting:

req report review
# Generate review status report with metrics

Best Practices

When creating a requirement with parents:

# Create requirement
req add SYS --parents USR-001

# Fingerprint is captured immediately

This ensures the fingerprint represents the baseline.

Periodically check for fingerprint mismatches:

# Check for suspect links
req suspect

# Before committing changes
req suspect || (echo "Review needed" && exit 1)

# In CI/CD pipeline
req suspect

After reviewing parent changes and updating children:

# Accept individual link
req accept SYS-001 USR-001

# Or accept all after bulk review
req accept --all

This updates fingerprints to acknowledge the review.

4. Document Review Process

Include fingerprint checking in your review process:

## Requirement Review Checklist

1. Check for suspect links: `req suspect`
2. For each suspect link:
   - Review parent changes
   - Review child requirement text
   - Update child if needed
   - Accept link: `req accept CHILD PARENT`
3. Verify all clean: `req suspect`
4. Commit changes

5. Avoid Trivial Changes

Minimize whitespace-only or formatting changes to reduce fingerprint churn:

  • Use consistent formatting from the start
  • Configure editor to preserve formatting
  • Avoid unnecessary reformatting

Troubleshooting

Unexpected Fingerprint Changes

Issue: Fingerprint changed but content looks the same.

Causes:

  1. Whitespace changes (trailing spaces, blank lines)
  2. Tag modifications
  3. Character encoding differences

Diagnosis:

# Show all changes including whitespace
git diff --ws-error-highlight=all USR-001.md

Fingerprint Not Updating

Issue: Changed requirement but fingerprint seems unchanged.

Explanation: Fingerprints are stored in parent references, not in the requirement itself.

Check: Look at a child requirement's parent reference to see the fingerprint.

Manual Fingerprint Edit

Issue: Accidentally edited a fingerprint in frontmatter.

Impact: Child will show incorrect fingerprint for parent.

Fix: Re-link the requirement:

req link SYS-001 USR-001
# This recalculates and stores the correct fingerprint

Summary

Key Concepts:

  • Fingerprint: SHA256 hash of requirement content and tags
  • Purpose: Detect when parent requirements change
  • Storage: Stored in child's parent reference
  • Automatic: Computed when linking requirements
  • Immutable: Old fingerprints preserved in children, enabling change detection

What's Included: Markdown body + tags

What's Excluded: HRID, UUID, timestamps, parent relationships

Use Cases: Change detection, impact analysis, review tracking

Commands Available:

  • req suspect - List all suspect links (fingerprint mismatches)
  • req accept <CHILD> <PARENT> - Accept suspect link after review
  • req accept --all - Accept all suspect links

Current State: Basic suspect link detection implemented

Future: Advanced review workflows with state tracking and assignments

Next Steps

Review Workflows

Note: Basic suspect link detection is implemented. Advanced review workflow features (state tracking, assignments, notifications) are planned for future releases.

Review workflows enable teams to track which requirements need review after upstream changes are detected via fingerprint mismatches.

Requiem can now automatically detect and manage suspect links:

Commands

req suspect - List all requirements with fingerprint mismatches

req suspect

Example output:

Found 3 suspect link(s):

  SYS-001 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

  SYS-002 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

  SYS-005 → USR-004
    Stored fingerprint:  407c6e3413d5b3fa
    Current fingerprint: c28afe188a974322

Exit codes:

  • 0: No suspect links (all current)
  • 1: Suspect links found (useful for CI/CD)

req accept <CHILD> <PARENT> - Accept a suspect link after review

req accept SYS-001 USR-001
# Output: Accepted suspect link: SYS-001 → USR-001

req accept --all - Accept all suspect links

req accept --all
# Output:
# Accepted 3 suspect link(s):
#   SYS-001 → USR-001
#   SYS-002 → USR-001
#   SYS-005 → USR-004

Basic Workflow

# 1. Check for suspect links
req suspect

# 2. Review parent changes
vim USR-001.md

# 3. Review and update affected children
vim SYS-001.md
vim SYS-002.md

# 4. Accept links after review
req accept SYS-001 USR-001
req accept SYS-002 USR-001

# Or accept all at once
req accept --all

# 5. Verify clean
req suspect
# Output: No suspect links found.

CI/CD Integration

Use in continuous integration:

#!/bin/bash
# Fail build if suspect links exist
req suspect
if [ $? -ne 0 ]; then
    echo "ERROR: Requirements need review"
    exit 1
fi

Or in GitHub Actions:

- name: Check for suspect links
  run: |
    req suspect || (echo "Requirements need review" && exit 1)

Planned Advanced Functionality

Automatic Review Triggers

When a parent requirement changes:

  1. Requiem detects fingerprint mismatch in child requirements
  2. Child requirements are flagged as "needs review"
  3. Team members are notified (configurable)
  4. Reviews are tracked until completed

Review States

Requirements will have review states:

  • Current: No parent changes; requirement is up to date
  • Suspect: Parent changed (fingerprint mismatch); needs review
  • Under Review: Review in progress
  • Reviewed: Review completed; requirement updated as needed
  • Approved: Reviewed and approved; baseline updated

Commands (Planned)

# Check for requirements needing review
req check

# Mark requirement as under review
req review start SYS-001

# Complete review and update fingerprint
req review complete SYS-001

# Show review status
req status

# Generate review report
req report review

Motivation

The Problem

Scenario: A user requirement changes. Which system requirements are affected?

Current state: Manual tracking required.

Example:

  1. Edit USR-001: Change email validation rules
  2. SYS-001, SYS-002, and SYS-005 reference USR-001
  3. Challenge: Remember to review all three system requirements
  4. Risk: Forget to review one; inconsistency results

The Solution

Automatic review tracking:

  1. Edit USR-001
  2. Requiem automatically flags SYS-001, SYS-002, SYS-005 as "needs review"
  3. Team dashboard shows requirements pending review
  4. Reviews are tracked and reported
  5. Nothing falls through the cracks

How It Works (Current Implementation)

Step 1: Make Changes

Edit a requirement:

vim USR-001.md  # Make your changes

The fingerprint of USR-001 automatically changes when content or tags change.

Find affected children:

req suspect

Output:

Found 3 suspect link(s):

  SYS-001 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

  SYS-002 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

  SYS-005 → USR-004
    Stored fingerprint:  407c6e3413d5b3fa
    Current fingerprint: c28afe188a974322

Step 3: Conduct Review

Review each affected requirement:

# Review parent changes
vim USR-001.md

# Review child and update if needed
vim SYS-001.md

After review, accept the fingerprint change:

# Accept individual link
req accept SYS-001 USR-001

# Or accept all at once
req accept --all

Output:

Accepted 3 suspect link(s):
  SYS-001 → USR-001
  SYS-002 → USR-001
  SYS-005 → USR-004

Step 5: Verify Clean

Confirm no suspect links remain:

req suspect
# Output: No suspect links found.

How Advanced Features Will Work (Planned)

Review State Tracking

Track review progress with states:

req review start SYS-001
# - Marks requirement as "under review"
# - Records reviewer and timestamp

req review complete SYS-001
# - Marks requirement as "reviewed"
# - Updates parent fingerprints
# - Clears review flag

Status Reports

Generate review reports:

req report review

Output:

Review Status Report (2025-07-22)

Pending Reviews:
  SYS-002: parent USR-001 changed (flagged 3 days ago)
  SYS-005: parent USR-001 changed (flagged 3 days ago)

Recently Reviewed:
  SYS-001: reviewed by alice@example.com (2025-07-22)

All Current:
  SYS-003, SYS-004, ...

Use Cases

Use Case 1: Change Impact Analysis

Scenario: Proposing a change to a critical requirement.

Question: What's the impact?

Workflow:

  1. Identify requirement to change (USR-001)
  2. Check impact:
req impact USR-001
  1. Output shows all descendants:
Requirements that depend on USR-001:
  Direct children:
    SYS-001, SYS-002, SYS-005
  Indirect descendants:
    SWR-001, SWR-003 (via SYS-001)
    TST-001, TST-002 (via SYS-001, SYS-002)

Total affected: 7 requirements
  1. Decide if change is worth the review burden

Use Case 2: Release Readiness

Scenario: Preparing for a release.

Question: Are all requirements reviewed and current?

Workflow:

req status

Sample output:

Requirement Counts
==================
Kind       | Count
-----------+-----
SYS        | 118
TST        | 24
USR        | 6
-----------+-----
Total      | 148

Suspect links: 3

If the command exits with code 1, use the suspect link total as your release checklist—clear them before shipping:

req check
# Review each flagged requirement
req review complete ...

Use Case 3: Compliance Audits

Scenario: Demonstrating requirements traceability for audit.

Goal: Show that all requirements were reviewed after changes.

Workflow:

req report audit --since 2025-01-01

Output:

Audit Report: Jan 1 - Jul 22, 2025

Requirements Changed: 23
  - USR-001, USR-005, SYS-003, ...

Reviews Conducted: 47
  - All downstream requirements reviewed
  - Average review time: 2.3 days

Compliance: ✓ PASS
  - All changed requirements reviewed
  - All affected descendants reviewed

Configuration (Planned)

Review Policies

# config.toml (planned)
[review]
# Automatically flag children when parent changes
auto_flag = true

# Require review completion before allowing further changes
block_on_pending_review = false

# Notification settings
notify_on_flag = true
notification_email = "team@example.com"

# Review SLA (days)
review_sla = 7

Review Rules

# config.toml (planned)
[review.rules]
# Require review for specific requirement kinds
require_review_for = ["USR", "SYS"]

# Skip review for certain kinds (e.g., documentation)
skip_review_for = ["DOC"]

# Require multiple approvers for critical requirements
require_approvals = 2  # For requirements tagged "critical"

Integration

Git Integration

Reviews tracked alongside code changes:

# Edit requirement
vim USR-001.md

# Flag affected requirements
req check

# Create PR with review tracking
git checkout -b update-usr-001
git add USR-001.md
git commit -m "Update USR-001: clarify email validation"

# PR description includes:
# - Changed requirement
# - Affected requirements
# - Review checklist

CI/CD Integration

# .github/workflows/requirements.yml (planned)
- name: Check review status
  run: |
    req check
    if [ $? -ne 0 ]; then
      echo "Requirements need review"
      exit 1
    fi

Issue Tracker Integration

Automatically create issues for flagged requirements:

req check --create-issues
# Creates GitHub/Jira issues for each requirement needing review

Current Workflow Examples

Example 1: Daily Review Check

Check for suspect links before starting work:

#!/bin/bash
# daily-check.sh

echo "Checking for suspect links..."
req suspect

if [ $? -eq 0 ]; then
    echo "✓ All requirements current"
else
    echo "⚠ Review needed - see above"
fi

Example 2: Pre-Commit Hook

Prevent commits with unreviewed changes:

#!/bin/bash
# .git/hooks/pre-commit

req suspect
if [ $? -ne 0 ]; then
    echo "ERROR: Suspect links found. Run 'req suspect' to see them."
    echo "Review and accept links before committing."
    exit 1
fi

Example 3: Pull Request Workflow

# 1. After making changes
git add -A
git commit -m "Update USR-001 validation rules"

# 2. Check for suspect links
req suspect

# 3. Review and update affected requirements
vim SYS-001.md
vim SYS-002.md

# 4. Accept all after review
req accept --all

# 5. Commit accepted fingerprints
git add -A
git commit -m "Accept fingerprints after USR-001 changes"

# 6. Push
git push

Example 4: Bulk Review Session

Review all pending changes at once:

# List all suspect links
req suspect > review-list.txt

# Review each one
vim SYS-001.md
vim SYS-002.md
# ... review all

# Accept all at once
req accept --all

# Verify clean
req suspect

Supplementary Tracking (Optional)

While req suspect and req accept handle basic detection and acceptance, you may want additional tracking:

Git Commit Messages

Document reviews in commit messages:

git commit -m "Review SYS-001 after USR-001 change

USR-001 updated email validation rules.
Reviewed SYS-001 and verified consistency.
No changes needed to SYS-001.

Accepted fingerprint: c4020419ead000e9"

Issue Tracking

Create issues for complex reviews:

## Review affected requirements after USR-001 change

- [x] SYS-001: Reviewed, no changes needed
- [x] SYS-002: Updated validation logic
- [ ] SYS-005: Waiting for clarification

Tags in Frontmatter

Track review priority with tags:

# SYS-001.md
tags:
- high-priority
- security-critical

Future Enhancements

Beyond basic review workflows:

Advanced Features

Review assignments:

req review assign SYS-001 --to alice@example.com

Review templates:

req review start SYS-001 --template checklist.md
# Provides structured review checklist

Review history:

req history SYS-001
# Shows all reviews and changes over time

Bulk operations:

req review complete SYS-001 SYS-002 SYS-003
# Complete multiple reviews at once

Integrations

Slack/Teams notifications:

@alice Your review is needed: SYS-001 (parent changed)

Dashboard UI: Web dashboard showing review status, pending items, team metrics.

Approval workflows: Multi-step approval for critical requirements.

Implementation Status

Current status: Partially implemented

Available now:

  • req suspect - Detect fingerprint mismatches
  • req accept <CHILD> <PARENT> - Accept individual suspect links
  • req accept --all - Accept all suspect links
  • ✅ CI/CD integration via exit codes

Planned for future releases:

  • ⏳ Review state tracking (under review, reviewed, approved)
  • ⏳ Review assignments and notifications
  • ⏳ Status reports and dashboards
  • ⏳ Review history and audit logs
  • ⏳ Multi-approver workflows

See GitHub repository for updates.

Contributing

Interested in helping implement advanced review workflow features? See the project repository for contribution guidelines.

Summary

Implemented features:

  • Automatic suspect link detection (req suspect)
  • Accepting suspect links after review (req accept)
  • CI/CD integration with proper exit codes
  • Batch operations (req accept --all)

Use these commands now:

req suspect              # List suspect links
req accept SYS-001 USR-001  # Accept single link
req accept --all         # Accept all suspect links

Planned advanced features:

  • Review state tracking (suspect → under review → reviewed → approved)
  • Commands: req review start/complete, req status, req report
  • Review assignments and team workflows
  • Notifications and integrations
  • Comprehensive audit reports

Current best practices:

  • Use req suspect regularly to check for changes
  • Review requirements manually before accepting
  • Use req accept to update fingerprints after review
  • Integrate into CI/CD pipelines for automated checks
  • Document reviews in git commit messages

Next Steps

  • Use Fingerprints for manual change detection
  • Implement workarounds for your workflow
  • Watch GitHub repository for implementation updates

Integration

Requiem integrates with existing tools in your development workflow. This chapter covers integration strategies and best practices.

Overview

Requiem's plain-text format enables integration with:

  • MdBook - Embed requirements in MdBook documentation
  • Sphinx - Include requirements in Sphinx-generated docs
  • Version Control - Git workflows and best practices

Philosophy: Compose, Don't Replace

Requiem doesn't aim to replace your existing documentation or development tools. Instead, it composes with them:

Documentation Tools

Requirements live alongside your documentation:

docs/
├── user-guide.md
├── architecture.md
├── requirements/
│   ├── USR-001.md    ← Requirements
│   └── SYS-001.md
└── api-reference.md

Documentation can reference or embed requirements directly.

Version Control

Requirements are plain text files that work naturally with Git:

  • Meaningful diffs
  • Branch and merge workflows
  • Pull request reviews
  • Complete history

Static Site Generators

MdBook and Sphinx can include requirement files in generated documentation:

# User Guide

## Requirements

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001 Plain Text Storage

## Statement

The tool shall store requirements as plain-text files that can be read and edited with any text editor.

## Rationale

Plain text storage enables:
- Version control integration with Git and other VCS tools
- Human review without specialized software
- Long-term archival and accessibility
- Integration with existing text-based workflows

## Acceptance Criteria

- Requirements are stored as `.md` (Markdown) files
- Files can be opened and edited in any text editor
- No proprietary or binary formats are required
- Files are compatible with standard version control systems

Requirements stay synchronized with documentation automatically.

CI/CD Pipelines

Validate requirements in continuous integration:

- name: Validate requirements
  run: req clean

Catch errors before merging.

Custom Tools

Plain text enables custom tooling:

# Custom analysis script
import glob

for req_file in glob.glob("USR-*.md"):
    # Parse, analyze, generate reports, etc.

Integration Patterns

Pattern 1: Standalone Requirements

Requirements in dedicated directory:

project/
├── src/           ← Source code
├── requirements/  ← Requirements (separate)
│   ├── config.toml
│   └── USR-001.md
└── docs/          ← Documentation (separate)

Best for: Clear separation of concerns, formal requirements management.

Pattern 2: Requirements with Documentation

Requirements embedded in documentation:

docs/
├── config.toml
├── user-guide.md
├── USR-001.md      ← Mixed with docs
├── architecture.md
└── SYS-001.md      ← Mixed with docs

Configuration: allow_unrecognised = true (to ignore non-requirement markdown files).

Best for: Integrated documentation, technical specifications.

Pattern 3: Monorepo with Multiple Projects

Each project has its own requirements:

monorepo/
├── project-a/
│   └── requirements/
│       └── USR-001.md
├── project-b/
│   └── requirements/
│       └── USR-001.md
└── shared/
    └── requirements/
        └── CORE-USR-001.md

Best for: Multi-project organizations, shared requirements.

Integration Benefits

Single Source of Truth

Requirements are defined once, referenced everywhere:

  • User documentation includes requirement text
  • Design docs reference requirements
  • Test plans trace to requirements
  • Code comments link to requirements

Changes propagate automatically (when using includes/references).

Automated Consistency

CI/CD ensures requirements remain valid:

# .github/workflows/requirements.yml
- run: req clean

Prevents broken traceability or invalid formatting.

Developer-Friendly

Plain text means developers can:

  • Use their preferred editor
  • Search with grep/ripgrep
  • Script with Python/Bash
  • Review in pull requests

No context switching to specialized tools.

Audit Trail

Git provides complete history:

# See all changes to a requirement
git log -p USR-001.md

# See who last modified
git blame USR-001.md

# See what changed in a sprint
git log --since="2 weeks ago" -- requirements/

Next Steps

Explore specific integrations:

Using with MdBook

MdBook is a popular tool for creating documentation from Markdown files. Requiem integrates seamlessly with MdBook, allowing requirements to live alongside documentation.

Overview

Requiem requirements are Markdown files, making them naturally compatible with MdBook. You can:

  • Include requirements in your MdBook table of contents
  • Embed requirements in documentation chapters
  • Mix requirements with narrative documentation
  • Generate complete documentation sites with embedded requirements

Basic Setup

Project Structure

my-book/
├── book.toml          ← MdBook configuration
└── src/
    ├── SUMMARY.md     ← Table of contents
    ├── config.toml    ← Requiem configuration
    ├── chapter1.md    ← Documentation
    ├── USR-001.md     ← Requirement
    └── USR-002.md     ← Requirement

Requiem Configuration

Since the src/ directory contains both requirements and documentation, configure Requiem to allow non-requirement files:

src/config.toml:

_version = "1"
allow_unrecognised = true  # Important: allows chapter1.md, SUMMARY.md, etc.

MdBook Configuration

book.toml:

[book]
title = "My Project Documentation"
authors = ["Your Name"]
language = "en"
src = "src"

[build]
build-dir = "book"

No special MdBook configuration needed for Requiem requirements!

Including Requirements in Table of Contents

Requirements can be listed in SUMMARY.md like any other chapter:

src/SUMMARY.md:

# Summary

[Introduction](./introduction.md)

# Requirements

- [User Requirements](./user-requirements.md)
  - [USR-001: User Authentication](./USR-001.md)
  - [USR-002: Data Export](./USR-002.md)
  - [USR-003: Email Validation](./USR-003.md)

- [System Requirements](./system-requirements.md)
  - [SYS-001: Authentication Service](./SYS-001.md)
  - [SYS-002: Export API](./SYS-002.md)

# User Guide

- [Getting Started](./getting-started.md)
- [Features](./features.md)

Requirements appear as chapters in the generated book. The HRID in the first heading (e.g., # USR-001 User Authentication) becomes the page title automatically.

Embedding Requirements

Use MdBook's include feature to embed requirements in documentation chapters:

src/user-guide.md:

# User Guide

## Authentication

Our authentication system satisfies the following requirement:

{{#include USR-001.md}}

To log in, navigate to...

When MdBook builds, USR-001.md content is embedded directly.

Selective Inclusion

Include only the requirement body (skip frontmatter but keep the heading):

{{#include USR-001.md:6:}}

This skips the YAML frontmatter and includes the heading and body.

Line counting:

---                    ← Line 1
_version: '1'
uuid: ...
created: ...
---                    ← Line 5
# USR-001 Title        ← Line 6 (keep this!)

Requirement text...    ← Line 7 onwards

Adjust the line number based on your frontmatter length. The heading with the HRID should typically be kept as it provides context.

Formatting Requirements

Display Frontmatter

To show frontmatter in documentation:

src/requirements-format.md:

# Requirement Format

Requirements include metadata in YAML frontmatter:

{{#include USR-001.md}}

MdBook renders the entire file, including frontmatter as a code block.

Hide Frontmatter

To show only the requirement text:

Option 1: Use line ranges

{{#include USR-001.md:7:}}

Option 2: Create requirement summary files

src/usr-001-summary.md:

<!-- Manually maintained summary without frontmatter -->
The system shall validate user email addresses according to RFC 5322.

Then include the summary file in documentation.

Custom Formatting with Preprocessors

For advanced formatting (e.g., extracting specific fields), use MdBook preprocessors:

  • mdbook-linkcheck - Validate links
  • mdbook-toc - Generate table of contents
  • Custom preprocessor - Extract HRID, UUID, parent links from frontmatter

Working Example

See the complete example in the Requiem repository:

git clone https://github.com/danieleades/requirements-manager
cd requirements-manager/examples/mdbook

Example Structure

examples/mdbook/
├── book.toml
├── src/
│   ├── SUMMARY.md
│   ├── chapter_1.md
│   ├── USR-001.md
│   └── USR-002.md
└── README.md

Build the Example

  1. Install MdBook:
cargo install mdbook
  1. Build the book:
mdbook build
  1. View output:
mdbook serve --open

Your browser opens showing the documentation with requirements included.

Best Practices

1. Organize by Type

Group requirements in SUMMARY.md:

# Summary

# User Requirements
- [USR-001](./USR-001.md)
- [USR-002](./USR-002.md)

# System Requirements
- [SYS-001](./SYS-001.md)
- [SYS-002](./SYS-002.md)

2. Use Subdirectories

For large projects, organize requirements in subdirectories:

src/
├── SUMMARY.md
├── requirements/
│   ├── user/
│   │   ├── USR-001.md
│   │   └── USR-002.md
│   └── system/
│       ├── SYS-001.md
│       └── SYS-002.md
└── guides/
    └── user-guide.md

SUMMARY.md:

# Summary

# Requirements
- [User Requirements](./requirements/user/USR-001.md)
- [System Requirements](./requirements/system/SYS-001.md)

Link between requirements using standard Markdown links:

USR-001.md:

This requirement is implemented by [SYS-001](./SYS-001.md).

MdBook generates clickable links in the output.

4. Embed in Context

Embed requirements in relevant documentation sections:

user-guide.md:

# User Guide

## Email Validation

{{#include requirements/USR-003.md:7:}}

To validate emails, the system checks...

Keeps requirements and documentation synchronized.

5. Separate Config

Use separate config.toml for Requiem:

src/
├── config.toml      ← Requiem config (allow_unrecognised = true)
├── book.toml        ← Don't confuse with MdBook config
└── ...

Note: MdBook's config is book.toml in the root, not in src/.

Limitations

Frontmatter Rendering

MdBook doesn't parse YAML frontmatter specially. It renders as:

---
_version: '1'
uuid: 4bfeb7d5-...
created: 2025-07-22T12:19:56.950194157Z
---

Requirement text...

The frontmatter appears as a code block (triple-dash markers).

Workaround: Use line ranges to skip frontmatter (see Formatting Requirements).

No Dynamic Traceability

MdBook doesn't generate traceability matrices or parent-child diagrams automatically.

Workaround: Generate diagrams with external tools and include as images:

# Traceability

![Requirement Hierarchy](./diagrams/traceability.svg)

No HRID Validation

MdBook doesn't validate requirement references.

Workaround: Use CI to validate:

# .github/workflows/docs.yml
- name: Validate requirements
  run: req clean
  working-directory: ./src

- name: Build documentation
  run: mdbook build

Advanced Techniques

Generating Traceability Pages

Use scripts to generate traceability documentation:

generate-traceability.sh:

#!/bin/bash
# Generate a markdown page showing parent-child relationships

echo "# Requirement Traceability" > traceability.md
echo "" >> traceability.md

for req in USR-*.md; do
    hrid=$(basename "$req" .md)
    echo "## $hrid" >> traceability.md
    # Extract and format parent links
    # ...
done

Run before MdBook build:

./generate-traceability.sh
mdbook build

Custom MdBook Preprocessor

Create a preprocessor to enhance requirement rendering:

Rust preprocessor example:

#![allow(unused)]
fn main() {
// Extract HRID and UUID from frontmatter
// Add custom formatting
// Generate cross-reference links
}

See MdBook documentation for details.

GitHub Pages Deployment

Host your requirements documentation:

# .github/workflows/deploy.yml
name: Deploy Documentation

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Install MdBook
        run: cargo install mdbook
      - name: Build book
        run: mdbook build
        working-directory: ./docs
      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs/book

Example Documentation Structure

Comprehensive documentation with requirements:

docs/
├── book.toml
└── src/
    ├── SUMMARY.md
    ├── config.toml             ← Requiem config
    │
    ├── introduction.md          ← Narrative docs
    ├── architecture.md
    ├── getting-started.md
    │
    ├── requirements/            ← Requirements
    │   ├── user/
    │   │   ├── USR-001.md
    │   │   └── USR-002.md
    │   ├── system/
    │   │   ├── SYS-001.md
    │   │   └── SYS-002.md
    │   └── traceability.md      ← Generated
    │
    └── user-guide/              ← User guides
        ├── authentication.md    ← Embeds USR-001, SYS-001
        └── export.md            ← Embeds USR-002, SYS-002

Troubleshooting

Requirements Not Appearing in Book

Problem: Requirements listed in SUMMARY.md don't appear.

Diagnosis:

  1. Check file paths in SUMMARY.md are correct
  2. Ensure files exist at specified paths
  3. Run mdbook build -v for verbose output

Solution: Verify paths match file structure exactly.

Frontmatter Renders as Code Block

Problem: YAML frontmatter shows as markdown code block.

Explanation: Expected behavior. MdBook doesn't parse YAML frontmatter.

Solution: Use line ranges to skip frontmatter (see Selective Inclusion).

Requiem Validation Fails

Problem: req clean reports errors about non-requirement files.

Solution: Set allow_unrecognised = true in config.toml:

_version = "1"
allow_unrecognised = true

Includes Don't Work

Problem: {{#include USR-001.md}} doesn't embed content.

Diagnosis:

  1. Check file path is correct relative to including file
  2. Check MdBook version (includes supported in 0.3.0+)

Solution: Use correct relative paths:

{{#include ./USR-001.md}}  # If in same directory
{{#include ../requirements/USR-001.md}}  # If in subdirectory

Summary

Key Points:

  • Requiem requirements are compatible with MdBook out of the box
  • Set allow_unrecognised = true in Requiem config when mixing with docs
  • Include requirements in SUMMARY.md or embed with {{#include}}
  • Use line ranges to skip frontmatter if desired
  • Combine requirements with narrative documentation for comprehensive docs

Benefits:

  • Single source of truth
  • Requirements stay synchronized with docs
  • Easy navigation and search
  • Professional-looking documentation

Limitations:

  • Frontmatter renders as code block
  • No automatic traceability diagrams
  • No HRID validation (use external tools)

Next Steps

Using with Sphinx

Sphinx is a powerful documentation generator widely used in Python projects. Requiem requirements integrate seamlessly with Sphinx using the MyST Parser extension.

Overview

Sphinx traditionally uses reStructuredText (RST), but with the MyST Parser extension, Sphinx can process Markdown files including Requiem requirements.

Key compatibility features:

  • MyST Parser treats YAML frontmatter as page metadata (doesn't render it)
  • HRIDs in headings (e.g., # USR-001 Title) work naturally as page titles
  • Requirements can be included in toctrees or embedded in documentation

Setup

Prerequisites

  • Python 3.7 or later
  • Sphinx
  • MyST Parser extension

Installation

Using pip:

pip install sphinx myst-parser

Using uv (recommended):

uv pip install sphinx myst-parser

Project Structure

docs/
├── conf.py             ← Sphinx configuration
├── index.md            ← Main documentation
├── requirements/       ← Requirements directory
│   ├── config.toml     ← Requiem configuration
│   ├── USR-001.md
│   ├── USR-002.md
│   ├── SYS-001.md
│   └── SYS-002.md
└── guides/
    └── user-guide.md

Sphinx Configuration

Configure Sphinx to use MyST Parser for Markdown:

conf.py:

project = 'My Project'
copyright = '2025, Your Name'
author = 'Your Name'

# Add MyST Parser extension
extensions = ["myst_parser"]

# Exclude non-documentation files
exclude_patterns = [
    '_build',
    'Thumbs.db',
    '.DS_Store',
    'requirements/config.toml',  # Exclude Requiem config
]

html_theme = 'alabaster'  # Or your preferred theme

Requiem Configuration

Since requirements live in a subdirectory with other Sphinx content, configure Requiem appropriately:

requirements/config.toml:

_version = "1"
# Strict mode OK here since requirements are in dedicated directory
allow_unrecognised = false

Including Requirements

Option 1: Direct Inclusion via Table of Contents

Create a toctree including requirement files:

index.md:

# Project Documentation

## Contents

\```{toctree}
:maxdepth: 2

guides/user-guide
requirements/USR-001
requirements/USR-002
requirements/SYS-001
\```

Requirements appear as pages in generated documentation with the HRID-containing heading as the page title.

Option 2: Include Directive

Use the MyST {include} directive to embed requirements:

guides/user-guide.md:

# User Guide

## Authentication

Our authentication system satisfies this requirement:

\```{include} ../requirements/USR-001.md
\```

The entire requirement (excluding frontmatter) is embedded in the guide.

Option 3: Literalinclude for Examples

To show requirements as code examples:

requirements-format.md:

# Requirement Format

Requirements are Markdown files with YAML frontmatter:

\```{literalinclude} requirements/USR-001.md
:language: markdown
\```

HRID in Headings

Requiem stores HRIDs in the first markdown heading (e.g., # USR-001 Title) rather than in YAML frontmatter.

Benefits for Sphinx

  • The first heading becomes the natural page title
  • Sphinx uses the heading text for navigation and cross-references
  • The HRID is visible in the rendered documentation
  • No special processing needed to extract the HRID

Example

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
---
# USR-001 Plain Text Storage

Requirements are stored as plain-text files...

Sphinx renders this with "USR-001 Plain Text Storage" as the page title. The YAML frontmatter is treated as page metadata and doesn't appear in the rendered output.

Working Example

The Requiem repository includes a complete Sphinx example:

git clone https://github.com/danieleades/requirements-manager
cd requirements-manager/examples/sphinx

Build the Example

  1. Install dependencies:
uv pip install -r requirements.txt

Or with pip:

pip install sphinx myst-parser
  1. Build documentation:
make html
  1. View output:
# Open _build/html/index.html in your browser

Best Practices

1. Dedicated Requirements Directory

Keep requirements in a separate directory:

docs/
├── conf.py
├── requirements/          ← Requirements
│   ├── config.toml
│   └── *.md
└── guides/               ← Other docs
    └── *.md

Benefits:

  • Clear separation between requirements and narrative docs
  • Easier Requiem configuration
  • Simpler to manage

2. Create Requirement Indexes

Generate index pages for requirement types:

requirements/user-requirements.md:

# User Requirements

\```{toctree}
:maxdepth: 1

USR-001
USR-002
USR-003
\```

3. Cross-Reference with Sphinx Roles

Use Sphinx's cross-referencing:

guides/user-guide.md:

See {doc}`requirements/USR-001` for authentication requirements.

Sphinx generates proper links automatically.

4. Organize by Type

Structure your toctree to group requirements:

\```{toctree}
:maxdepth: 2

User Requirements <requirements/user-requirements>
System Requirements <requirements/system-requirements>
Specifications <requirements/specifications>
\```

Troubleshooting

MyST Parser Not Found

Error: Extension error: Could not import extension myst_parser

Solution: Install MyST Parser:

pip install myst-parser

Markdown Files Not Processed

Problem: Markdown files don't appear in generated docs.

Solution: Ensure MyST Parser is in extensions list in conf.py:

extensions = ["myst_parser"]

Include Directive Not Working

Problem: {include} directive doesn't embed content.

Solution: Check file path is correct relative to the source file:

\```{include} ../requirements/USR-001.md
\```

Requirements Not in Table of Contents

Problem: Requirements don't appear in navigation.

Solution: Add requirements to a toctree directive in your index or section files.

Summary

Key Points:

  • Use MyST Parser extension for Markdown support
  • MyST treats YAML frontmatter as metadata (doesn't render it)
  • HRIDs in headings work naturally as page titles
  • Include requirements via toctree or include directives
  • Keep requirements in dedicated directory

Benefits:

  • Seamless integration with Python documentation
  • Requirements alongside API docs and guides
  • Professional HTML output with themes
  • Cross-referencing and search

Limitations:

  • Requires MyST Parser (additional dependency)
  • Less "native" than MdBook (Sphinx primarily RST-focused)

Next Steps

Version Control Best Practices

Requiem's plain-text format makes requirements ideal for version control. This chapter covers Git workflows and best practices.

Why Version Control Matters

Requirements benefit from version control:

  • Complete history: Track all changes over time
  • Audit trail: Know who changed what and when
  • Branching: Develop requirements in parallel
  • Review: Use pull requests for requirement reviews
  • Rollback: Revert problematic changes
  • Tagging: Mark requirement baselines (releases)

Git Basics for Requirements

Initial Setup

Create a Git repository for your requirements:

mkdir my-requirements
cd my-requirements
git init

# Create first requirement
req add USR
git add config.toml USR-001.md
git commit -m "Initial commit: add USR-001"

Adding Requirements

When creating requirements:

# Create requirement
req add USR

# Stage and commit
git add USR-002.md
git commit -m "Add USR-002: user data export requirement"

Editing Requirements

When modifying requirements:

# Edit requirement
vim USR-001.md

# Review changes
git diff USR-001.md

# Stage and commit
git add USR-001.md
git commit -m "Update USR-001: clarify email validation format"

Linking Requirements

When linking requirements:

# Create link
req link SYS-001 USR-001

# Both files change (child gets parent reference)
git diff

# Commit both
git add SYS-001.md
git commit -m "Link SYS-001 to USR-001"

Commit Message Best Practices

Format

Use clear, descriptive commit messages:

Bad:

git commit -m "update"
git commit -m "fix typo"
git commit -m "changes"

Good:

git commit -m "Add USR-042: user data export requirement"
git commit -m "Update USR-001: change email validation to RFC 5322"
git commit -m "Link SYS-001 to USR-001 and USR-002"

Structure

Use conventional commit format:

<type>: <HRID>: <description>

[optional body]

[optional footer]

Types:

  • add: New requirement
  • update: Modify existing requirement
  • link: Create requirement link
  • remove: Delete requirement
  • refactor: Reorganize without changing content
  • docs: Update documentation (non-requirement changes)

Examples:

# Add new requirement
git commit -m "add: USR-042: user data export"

# Update existing
git commit -m "update: USR-001: clarify email validation

Changed from 'valid email' to 'RFC 5322 compliant'
to remove ambiguity."

# Link requirements
git commit -m "link: SYS-001 -> USR-001, USR-002

SYS-001 satisfies both user requirements for authentication."

# Bulk operation
git commit -m "refactor: reorganize requirements into subdirectories

- Move USR-*.md to user/
- Move SYS-*.md to system/
- Update config.toml"

Branching Strategies

Feature Branches

Develop requirements for new features in branches:

# Create feature branch
git checkout -b feature/payment-system

# Add requirements
req add USR  # USR-042
req add SYS  # SYS-012
# Edit and link requirements

# Commit changes
git add .
git commit -m "add: payment system requirements (USR-042, SYS-012)"

# Push for review
git push origin feature/payment-system

Requirement Change Branches

For significant requirement changes:

# Create change branch
git checkout -b change/update-usr-001

# Edit requirement
vim USR-001.md

# Update dependent requirements
req clean

# Commit
git add .
git commit -m "update: USR-001: clarify email validation

Updated email validation to reference RFC 5322.
Corrected parent HRIDs in dependent requirements."

# Create pull request
gh pr create

Release Branches

Stabilize requirements for releases:

# Create release branch
git checkout -b release/v1.0

# Freeze requirements (no new additions)
# Allow only bug fixes and clarifications

# Tag when stable
git tag v1.0.0
git push origin v1.0.0

Pull Request Workflows

Creating Pull Requests

When changing requirements:

  1. Create branch:
git checkout -b update-auth-requirements
  1. Make changes:
vim USR-001.md
req clean
  1. Commit:
git add -A
git commit -m "update: USR-001: strengthen password requirements"
  1. Push and create PR:
git push origin update-auth-requirements
gh pr create --title "Update authentication requirements" \
             --body "Strengthens password requirements to meet new security policy"

PR Description Template

Use a template for requirement PRs:

## Summary
Adds/updates/removes requirements for [feature/change].

## Changed Requirements
- USR-001: [description of change]
- SYS-005: [description of change]

## Impact Analysis
- Affects: SYS-001, SYS-003, TST-001
- Reviewed: ✓ All dependent requirements checked

## Checklist
- [x] `req clean` passes
- [x] Commit messages follow convention
- [x] Dependent requirements reviewed
- [x] Tests updated (if applicable)
- [ ] Approved by: @stakeholder

Reviewing Pull Requests

When reviewing requirement PRs:

  1. Check diffs carefully:
# Review line-by-line changes
gh pr diff 123
  1. Verify UUIDs unchanged:
# Ensure UUIDs haven't been modified
git diff main..HEAD -- '*.md' | grep 'uuid:'
  1. Check req clean passes:
# Validate requirements
req clean
  1. Review dependent requirements:
# Find affected requirements
grep -r "uuid: <changed-req-uuid>" *.md
  1. Approve and merge:
gh pr review 123 --approve
gh pr merge 123

Handling Conflicts

Merge Conflicts in Requirements

Conflicts occur when two branches modify the same requirement.

Example conflict:

<<<<<<< HEAD
The system shall validate emails using RFC 5321.
=======
The system shall validate emails using RFC 5322.
>>>>>>> feature/update-email-validation

Resolution:

  1. Understand both changes: Read both versions.

  2. Choose or combine: Decide which is correct or merge both:

The system shall validate emails using RFC 5322.
  1. Mark resolved:
git add USR-001.md
git commit

Frontmatter Conflicts

UUID conflicts (should never happen):

<<<<<<< HEAD
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
=======
uuid: 00000000-0000-0000-0000-000000000000
>>>>>>> other-branch

Resolution: Keep the original UUID (HEAD). Changing UUIDs breaks traceability.

Parent conflicts (both branches added parents):

<<<<<<< HEAD
parents:
- uuid: aaaa...
  hrid: USR-001
=======
parents:
- uuid: bbbb...
  hrid: USR-002
>>>>>>> other-branch

Resolution: Merge both parents:

parents:
- uuid: aaaa...
  hrid: USR-001
- uuid: bbbb...
  hrid: USR-002

Then run:

req clean  # Validate merged result

Tagging and Releases

Creating Baseline Tags

Tag stable requirement sets:

# Tag current state
git tag -a v1.0.0 -m "Release 1.0.0 requirements baseline"
git push origin v1.0.0

Naming Conventions

Use semantic versioning:

  • v1.0.0 - Major release
  • v1.1.0 - Minor release (new requirements)
  • v1.0.1 - Patch release (clarifications, typo fixes)

Or use date-based tags:

  • baseline-2025-07-22
  • release-2025-q3

Comparing Baselines

Compare requirement changes between releases:

# List changed requirements
git diff v1.0.0..v2.0.0 --name-only -- '*.md'

# Show detailed changes
git diff v1.0.0..v2.0.0 -- USR-001.md

# Generate changelog
git log v1.0.0..v2.0.0 --oneline -- '*.md'

Advanced Git Techniques

Git Blame for Requirements

See who last modified each line:

git blame USR-001.md

Output:

4bfeb7d5 (Alice  2025-07-20) The system shall validate
a1b2c3d4 (Bob    2025-07-22) user email addresses according
e5f6g7h8 (Alice  2025-07-23) to RFC 5322.

Git Log for Requirement History

View complete history:

# All commits affecting USR-001
git log -p USR-001.md

# One-line summary
git log --oneline USR-001.md

# Show who, when, what
git log --format="%h %an %ad %s" --date=short -- USR-001.md

Git Diff for Requirement Changes

Compare versions:

# Current vs. last commit
git diff HEAD~1 USR-001.md

# Current vs. specific commit
git diff a1b2c3d4 USR-001.md

# Between branches
git diff main..feature/update USR-001.md

# Ignore whitespace
git diff -w USR-001.md

Bisect to Find Breaking Changes

Find when a requirement changed incorrectly:

git bisect start
git bisect bad HEAD
git bisect good v1.0.0

# Git checks out middle commit
req clean  # Test if requirements are valid
git bisect good  # or 'bad'

# Repeat until found
git bisect reset

Ignoring Files

.gitignore for Requirements Projects

Exclude generated or temporary files:

.gitignore:

# Requiem temp files
*.tmp

# Editor files
*.swp
*.swo
*~
.vscode/
.idea/

# OS files
.DS_Store
Thumbs.db

# Build outputs (if using MdBook/Sphinx)
book/
_build/
_generated/

# Python
__pycache__/
*.pyc
.venv/

Don't ignore:

  • config.toml (Requiem configuration)
  • *.md (requirements)

CI/CD Integration

GitHub Actions

Validate requirements automatically:

.github/workflows/requirements.yml:

name: Requirements Validation

on: [push, pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install Requiem
        run: cargo install requirements-manager

      - name: Validate requirements
        run: req clean
        working-directory: ./requirements

      - name: Check for uncommitted changes
        run: |
          if [ -n "$(git status --porcelain)" ]; then
            echo "Error: req clean modified files. Run req clean locally."
            git diff
            exit 1
          fi

Pre-commit Hook

Validate before every commit:

.git/hooks/pre-commit:

#!/bin/bash

echo "Validating requirements..."
req clean

if [ $? -ne 0 ]; then
    echo "Error: Requirements validation failed"
    exit 1
fi

# Stage any changes made by req clean
git add -u

exit 0

Make executable:

chmod +x .git/hooks/pre-commit

Collaboration Best Practices

1. Clear Ownership

Define requirement ownership:

# CODEOWNERS
# Assign reviewers for requirement changes

requirements/USR-*.md @product-team
requirements/SYS-*.md @architecture-team
requirements/TST-*.md @qa-team

2. Require Reviews

Enforce PR reviews:

GitHub branch protection:

  • Require pull request reviews before merging
  • Require status checks (req clean) to pass
  • Require up-to-date branches

3. Communication

Use commit messages and PR descriptions to communicate:

  • Why the change was made
  • What requirements are affected
  • Who should review

4. Regular Syncs

Prevent divergence:

# Update from main frequently
git checkout feature/my-branch
git pull origin main
git merge main

# Resolve conflicts if any
req clean

5. Atomic Commits

One logical change per commit:

Bad:

# Single commit with unrelated changes
git commit -m "Add USR-042, update USR-001, fix typo in SYS-003"

Good:

# Separate commits
git commit -m "add: USR-042: user data export"
git commit -m "update: USR-001: clarify email validation"
git commit -m "fix: SYS-003: correct typo in authentication flow"

Troubleshooting

Large Diffs

Problem: Git diffs for requirement files are hard to read.

Solution: Use word-level diffs:

git diff --word-diff USR-001.md

Or color-words:

git diff --color-words USR-001.md

Accidental UUID Changes

Problem: Someone accidentally changed a UUID.

Detection:

# Find UUID changes
git log -p --all -S'uuid:' -- USR-001.md

Recovery:

# Restore correct UUID from history
git show a1b2c3d4:USR-001.md | grep 'uuid:'
# Manually fix or revert

Lost Requirements

Problem: Requirement file was deleted.

Recovery:

# Find when it was deleted
git log --all --full-history -- USR-099.md

# Restore from last good commit
git checkout a1b2c3d4 -- USR-099.md

Summary

Key Practices:

  1. Commit frequently with clear messages
  2. Use branches for features and changes
  3. Create PRs for reviews
  4. Validate with req clean before committing
  5. Tag releases for baselines
  6. Review carefully to catch UUID changes
  7. Resolve conflicts thoughtfully (never change UUIDs)
  8. Use CI/CD for automated validation

Benefits:

  • Complete audit trail
  • Easy collaboration
  • Reversible changes
  • Formal review process
  • Baseline management

Common Pitfalls:

  • Changing UUIDs (breaks traceability)
  • Poor commit messages (lost context)
  • Ignoring conflicts (inconsistent requirements)
  • Skipping validation (invalid requirements reach main)

Next Steps

Advanced Topics

This chapter covers advanced features and techniques for requirements management with Requiem.

Overview

Advanced topics include:

Current Capabilities

Requiem currently provides core functionality:

  • Plain-text requirements in Markdown
  • Human-readable IDs with namespace support
  • Parent-child relationships with multiple parents
  • Content fingerprinting for change detection
  • Fast parallel loading
  • Integration with MdBook and Sphinx

Planned Capabilities

Future releases will add:

  • Coverage reports: Analyze requirement traceability
  • Cycle detection: Find and report circular dependencies
  • Review workflows: Automated review triggering
  • Import/export: ReqIF, JSON, CSV formats
  • Validation rules: Custom requirement quality checks
  • Query language: Advanced filtering and searching

Contributing

These features are planned but not yet implemented. Interested in contributing? See the GitHub repository for:

  • Feature roadmap
  • Open issues
  • Contribution guidelines
  • Development setup

Workarounds

Until advanced features are implemented, consider these approaches:

Manual Coverage Analysis

Use scripts to analyze traceability:

#!/bin/bash
# Find USR requirements without SYS children

comm -23 \
  <(ls USR-*.md | sed 's/.md//' | sort) \
  <(grep -oh "USR-[0-9]*" SYS-*.md | sort -u)

Manual Cycle Detection

Trace requirement chains manually:

# Follow parent chain
grep "uuid:" USR-001.md  # Get UUID
grep "<uuid>" *.md        # Find children
# Repeat for each child

Export with Scripts

Generate reports in various formats:

import glob
import yaml
import re
import json

requirements = []
for path in glob.glob("*.md"):
    with open(path) as f:
        content = f.read()
    # Parse frontmatter and body
    # Add to requirements list

# Export as JSON
with open("requirements.json", "w") as f:
    json.dump(requirements, f, indent=2)

Next Steps

Explore planned features:

Coverage Reports

Note: Coverage reporting is planned but not yet implemented. This chapter describes how the feature will work when available.

Coverage reports analyze requirement traceability, identifying gaps in the requirement hierarchy and ensuring all requirements are properly traced.

What is Coverage?

Coverage measures how completely requirements are traced across levels:

  • Downstream coverage: Do all user requirements have system requirements?
  • Upstream coverage: Do all test cases trace to requirements?
  • Bidirectional traceability: Can you trace from user needs to implementation and tests?

Example

USR-001 ← User requirement
  ├─ SYS-001 ← System requirement (traced)
  └─ SYS-002 ← System requirement (traced)

USR-002 ← User requirement
  └─ (no children) ← Coverage gap!

SYS-003 ← System requirement
  └─ (no parents) ← Orphan requirement!

Coverage report identifies:

  • USR-002 has no system requirements (gap)
  • SYS-003 has no parent (orphan)

Planned Functionality

Coverage Analysis Command

req coverage

Output:

Coverage Report

User Requirements (USR):
  Total: 25
  With children: 23 (92%)
  Without children: 2 (8%)
    - USR-002: User data export
    - USR-018: Password recovery

System Requirements (SYS):
  Total: 47
  With parents: 45 (96%)
  With children: 43 (91%)
  Orphans: 2 (4%)
    - SYS-003: Logging service
    - SYS-029: Cache invalidation

Test Cases (TST):
  Total: 156
  With parents: 150 (96%)
  Orphans: 6 (4%)

Overall Coverage: 93%

Coverage by Kind

Analyze specific requirement kinds:

req coverage --kind USR

Output:

User Requirement Coverage

Total: 25

With children: 23 (92%)
  USR-001 → SYS-001, SYS-002
  USR-003 → SYS-005, SYS-006, SYS-007
  ...

Without children (gaps): 2 (8%)
  USR-002: User data export
  USR-018: Password recovery

Recommendation: Add system requirements for USR-002 and USR-018

Detailed Reports

Generate detailed coverage information:

req coverage --detailed > coverage-report.md

Output format (Markdown):

# Coverage Report

## Summary
- User Requirements: 92% covered
- System Requirements: 96% traced upstream, 91% traced downstream
- Tests: 96% traced

## Gaps

### User Requirements Without Children
- **USR-002**: User data export
  - Status: No system requirements
  - Action: Create SYS requirements

- **USR-018**: Password recovery
  - Status: No system requirements
  - Action: Create SYS requirements

### Orphan System Requirements
- **SYS-003**: Logging service
  - Status: No parent requirement
  - Action: Link to USR requirement or remove

...

Visual Reports

Generate coverage diagrams:

req coverage --format html > coverage.html

Features:

  • Interactive traceability matrix
  • Heatmap showing coverage density
  • Clickable requirement links
  • Filterable by kind, tag, or namespace

Use Cases

Use Case 1: Requirement Review

Scenario: Preparing for a requirements review.

Goal: Identify incomplete traceability.

Workflow:

# Generate coverage report
req coverage --detailed > review-report.md

# Review gaps
# - USR-002: No system requirements
# - SYS-003: Orphan requirement

# Fix gaps
req add SYS --parent USR-002  # Add missing SYS requirement
req link SYS-003 USR-007      # Link orphan to parent

# Verify
req coverage
# Coverage improved to 100%

Use Case 2: Release Readiness

Scenario: Ensuring all requirements are traced before release.

Goal: 100% coverage required for release.

Workflow:

# Check coverage
req coverage --minimum 100

# Output (if < 100%):
# Error: Coverage is 93%, minimum required is 100%
# Gaps:
#   - USR-002: No children
#   - USR-018: No children
#   - SYS-003: No parent

# Fix gaps...

# Verify
req coverage --minimum 100
# Success: Coverage is 100%

Use Case 3: Compliance Audit

Scenario: Demonstrating traceability for compliance audit.

Goal: Prove all user requirements are traced to implementation and tests.

Workflow:

# Generate audit report
req coverage --audit \
  --trace-from USR \
  --trace-to TST \
  --output audit-report.pdf

# Report shows:
# - Complete traceability chain: USR → SYS → SWR → TST
# - No gaps
# - All requirements covered

Configuration (Planned)

Coverage Rules

# config.toml (planned)
[coverage]
# Minimum coverage percentage required
minimum = 95

# Require specific kinds to have children
require_children = ["USR", "SYS"]

# Require specific kinds to have parents
require_parents = ["SYS", "SWR", "TST"]

# Allowed to have no children (leaf requirements)
leaf_kinds = ["TST", "DOC"]

# Allowed to have no parents (root requirements)
root_kinds = ["USR"]

Coverage Thresholds

[coverage.thresholds]
# Per-kind minimum coverage
USR = 100  # All user requirements must have children
SYS = 95   # 95% of system requirements must have children
SWR = 90   # 90% of software requirements must have children
TST = 100  # All tests must have parents

Report Formats

Plain Text

Simple text output:

req coverage

Markdown

Detailed Markdown report:

req coverage --format markdown > coverage.md

HTML

Interactive HTML dashboard:

req coverage --format html > coverage.html

JSON

Machine-readable output:

req coverage --format json > coverage.json

Example JSON:

{
  "timestamp": "2025-07-22T12:00:00Z",
  "overall_coverage": 93,
  "by_kind": {
    "USR": {
      "total": 25,
      "with_children": 23,
      "without_children": 2,
      "coverage": 92
    },
    "SYS": {
      "total": 47,
      "with_parents": 45,
      "with_children": 43,
      "coverage": 96
    }
  },
  "gaps": [
    {
      "hrid": "USR-002",
      "type": "no_children",
      "description": "User data export"
    }
  ]
}

CSV

Spreadsheet-compatible output:

req coverage --format csv > coverage.csv

Traceability Matrix

Generate traceability matrices showing parent-child relationships:

req coverage --matrix

Output (simplified):

         | USR-001 | USR-002 | USR-003
---------|---------|---------|---------
SYS-001  |    X    |         |
SYS-002  |    X    |         |    X
SYS-003  |         |         |
SYS-004  |         |         |    X

Features:

  • Rows: Child requirements
  • Columns: Parent requirements
  • X: Link exists
  • Empty: No link
  • Highlights gaps and orphans

Integration

CI/CD

Enforce coverage in CI:

# .github/workflows/requirements.yml (planned)
- name: Check requirement coverage
  run: |
    req coverage --minimum 95
    if [ $? -ne 0 ]; then
      echo "Coverage below minimum"
      req coverage --detailed
      exit 1
    fi

Pull Request Comments

Automatically comment on PRs with coverage impact:

- name: Coverage report
  run: |
    req coverage --format markdown > coverage.md
    gh pr comment ${{ github.event.number }} --body-file coverage.md

Dashboard Integration

Export coverage to dashboards:

# Export for Grafana/Prometheus
req coverage --format prometheus > metrics.txt

Metrics (Planned)

Coverage Percentage

coverage = (requirements_with_links / total_requirements) * 100

Downstream Coverage

downstream_coverage = (parents_with_children / total_parents) * 100

Upstream Coverage

upstream_coverage = (children_with_parents / total_children) * 100

Orphan Rate

orphan_rate = (requirements_without_parents / total_requirements) * 100

Workarounds (Until Implemented)

Manual coverage analysis:

Script to Find Gaps

#!/bin/bash
# find-gaps.sh

echo "USR requirements without SYS children:"
comm -23 \
  <(ls USR-*.md | sed 's/.md//' | sort) \
  <(grep -oh "USR-[0-9]*" SYS-*.md | sort -u)

echo ""
echo "SYS requirements without parents:"
for sys in SYS-*.md; do
    if ! grep -q "parents:" "$sys"; then
        echo "  $(basename "$sys" .md)"
    fi
done

Spreadsheet Analysis

Create a spreadsheet:

RequirementHas ParentsHas ChildrenCoverage
USR-001N/AYes
USR-002N/ANo
SYS-001YesYes
SYS-003NoNo

Track manually until coverage reporting is implemented.

Summary

Planned functionality:

  • Coverage percentage by requirement kind
  • Gap identification (requirements without parents/children)
  • Orphan detection
  • Traceability matrices
  • Multiple report formats (text, Markdown, HTML, JSON, CSV)
  • CI/CD integration
  • Configurable coverage thresholds

Use cases:

  • Requirement reviews
  • Release readiness checks
  • Compliance audits
  • Quality assurance

Timeline: Implementation planned for future release

Next Steps

Cycle Detection

Note: Cycle detection is planned but not yet implemented. This chapter describes how the feature will work when available.

Cycle detection identifies circular dependencies in requirement graphs, which are usually errors that break valid traceability hierarchies.

What are Cycles?

A cycle occurs when requirements form a circular dependency chain:

USR-001 → SYS-001 → SYS-002 → USR-001

Requirements form a loop: USR-001 depends on SYS-001, which depends on SYS-002, which depends back on USR-001.

Why Cycles are Problematic

Break hierarchy assumptions:

  • Requirements should form a Directed Acyclic Graph (DAG)
  • Cycles violate DAG properties

Logical impossibility:

  • A cannot be satisfied until B is satisfied
  • B cannot be satisfied until C is satisfied
  • C cannot be satisfied until A is satisfied
  • Nothing can be satisfied!

Review complexity:

  • Changes propagate indefinitely
  • Impossible to determine impact

Compliance issues:

  • Many standards require acyclic traceability
  • Auditors expect clear hierarchies

Example Cycles

Simple Cycle (2 requirements)

USR-001 → SYS-001 → USR-001

Why it happens: Accidental bi-directional linking.

Detection: SYS-001 lists USR-001 as parent; USR-001 lists SYS-001 as parent.

Complex Cycle (3+ requirements)

USR-001 → SYS-001 → SYS-002 → SWR-001 → USR-001

Why it happens: Accumulation of links over time without oversight.

Detection: Following parent chain eventually returns to starting requirement.

Self-Reference

USR-001 → USR-001

Why it happens: Data entry error.

Detection: Requirement lists itself as a parent.

Planned Functionality

Cycle Detection Command

req check-cycles

Output (if cycles found):

Error: Cycles detected in requirement graph

Cycle 1 (length 3):
  USR-001 → SYS-001 → SYS-002 → USR-001

Cycle 2 (length 2):
  SYS-005 → SWR-003 → SYS-005

Cycle 3 (self-reference):
  SWR-012 → SWR-012

Total cycles: 3

Fix these cycles to ensure valid traceability.

Output (no cycles):

No cycles detected. Requirement graph is acyclic.

Detailed Cycle Information

req check-cycles --detailed

Output:

Cycle 1:
  Path: USR-001 → SYS-001 → SYS-002 → USR-001
  Length: 3
  Requirements involved:
    - USR-001: User authentication
      Parent: SYS-002 (creates cycle)
    - SYS-001: Authentication service
      Parent: USR-001
    - SYS-002: Session management
      Parent: SYS-001

  Suggested fix:
    Remove parent link from USR-001 to SYS-002
    (User requirements should not depend on system requirements)

Visualization

Generate cycle diagrams:

req check-cycles --visualize > cycles.dot
dot -Tpng cycles.dot -o cycles.png

Output: Graph highlighting cyclic paths in red.

How Detection Works

Requiem will use DFS with cycle detection:

  1. Start from each requirement
  2. Follow parent links (or child links for reverse traversal)
  3. Track visited requirements in current path
  4. If revisit a requirement in current path: Cycle detected
  5. Report cycle: Full path from requirement back to itself

Example Walkthrough

Requirements:

USR-001 → SYS-001
SYS-001 → SYS-002
SYS-002 → USR-001  (creates cycle)

Detection:

1. Start at USR-001
2. Visit SYS-001 (parent of USR-001)
3. Visit SYS-002 (parent of SYS-001)
4. Visit USR-001 (parent of SYS-002)
5. USR-001 is already in path → Cycle detected!
6. Report: USR-001 → SYS-001 → SYS-002 → USR-001

Performance

  • Time complexity: O(V + E) where V = requirements, E = links
  • Expected runtime: Milliseconds for 1000s of requirements
  • Parallel detection: Possible for disconnected subgraphs

Use Cases

Use Case 1: Continuous Validation

Scenario: Automatically check for cycles in CI.

Workflow:

# .github/workflows/requirements.yml (planned)
- name: Check for cycles
  run: |
    req check-cycles
    if [ $? -ne 0 ]; then
      echo "Cycles detected!"
      req check-cycles --detailed
      exit 1
    fi

Benefit: Cycles are caught before merging.

Use Case 2: Fixing Legacy Requirements

Scenario: Inherited a requirement set with unknown quality.

Goal: Find and fix all cycles.

Workflow:

# Detect cycles
req check-cycles --detailed

# Output:
# Cycle 1: USR-001 → SYS-001 → SYS-002 → USR-001
# Suggested fix: Remove link from USR-001 to SYS-002

# Fix cycle
vim USR-001.md  # Remove SYS-002 from parents

# Verify
req check-cycles
# No cycles detected

Use Case 3: Incremental Checking

Scenario: Adding a new link between requirements.

Goal: Ensure the new link doesn't create a cycle.

Workflow:

# Add link
req link SWR-001 SYS-005

# Check if cycle created
req check-cycles

# If cycle:
# Error: Cycle detected: SYS-005 → ... → SWR-001 → SYS-005

# If no cycle:
# No cycles detected

Benefit: Immediate feedback; don't commit cycle-inducing links.

Breaking Cycles

Identify the "weakest" link in the cycle and remove it:

USR-001 → SYS-001 → SYS-002 → USR-001
                               ^^^^^^^
                        Remove this link

Criteria for "weakest":

  • Violates hierarchy (e.g., user requirement depending on system requirement)
  • Accidental or incorrect
  • Least impactful to remove

Strategy 2: Reverse Hierarchy

If requirements are at wrong levels, reassign:

Before (cycle):
  USR-001 → SYS-001
  SYS-001 → USR-002
  USR-002 → USR-001

After (fixed):
  USR-001, USR-002 → SYS-001
  (SYS-001 now has both as parents; no cycle)

Strategy 3: Introduce Intermediate Requirement

Break cycle by adding a requirement:

Before (cycle):
  USR-001 → SYS-001 → USR-001

After (fixed):
  USR-001 → SYS-001 → SYS-002
  (SYS-002 is new, breaks cycle)

Strategy 4: Merge Requirements

If cycle indicates redundancy, merge:

Before (cycle):
  REQ-A → REQ-B → REQ-A

After (merged):
  REQ-AB (combines A and B; no cycle)

Configuration (Planned)

Enable/Disable Cycle Checking

# config.toml (planned)
[cycles]
# Enable cycle detection
enabled = true

# Fail on cycle detection (exit with error)
fail_on_cycle = true

# Report self-references separately
detect_self_references = true

CI Integration

[cycles.ci]
# Run cycle detection in CI
enabled = true

# Block merge if cycles detected
block_on_cycle = true

Exceptions (Planned)

In rare cases, cycles might be intentional. Allow marking exceptions:

# USR-001.md (hypothetical)
---
_version: '1'
uuid: ...
parents:
- uuid: ...
  hrid: SYS-002
  cycle_exception: true  # Mark as intentional cycle
---

Or in config:

[cycles.exceptions]
# Allow specific cycles
allowed = [
    ["USR-001", "SYS-001", "USR-001"],
]

Use sparingly: Cycles are almost always errors.

Topological Sort

After ensuring no cycles, enable topological sorting:

req sort --topological

Output: Requirements in dependency order (parents before children).

Use case: Determine implementation order.

Dependency Depth

Analyze requirement depth in hierarchy:

req depth USR-001

Output:

USR-001:
  Depth: 0 (root requirement)
  Max descendant depth: 4

  Path to deepest descendant:
    USR-001 → SYS-001 → SWR-003 → TST-012

Workarounds (Until Implemented)

Manual cycle detection:

Script to Detect Simple Cycles

#!/usr/bin/env python3
import glob
import yaml
import re

def parse_requirement(path):
    with open(path) as f:
        content = f.read()
    match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
    if match:
        frontmatter = yaml.safe_load(match.group(1))
        return frontmatter
    return None

def find_cycles():
    # Build graph
    graph = {}
    for req_file in glob.glob("*.md"):
        hrid = req_file.replace('.md', '')
        frontmatter = parse_requirement(req_file)
        if frontmatter:
            parents = frontmatter.get('parents', [])
            parent_hrids = [p['hrid'] for p in parents]
            graph[hrid] = parent_hrids

    # Detect cycles with DFS
    def visit(req, path):
        if req in path:
            cycle = path[path.index(req):] + [req]
            print(f"Cycle detected: {' → '.join(cycle)}")
            return True
        if req not in graph:
            return False
        for parent in graph[req]:
            if visit(parent, path + [req]):
                return True
        return False

    for req in graph:
        visit(req, [])

if __name__ == '__main__':
    find_cycles()

Run:

python detect-cycles.py

Manual Inspection

For small requirement sets, manually trace parent chains:

  1. Pick a requirement (e.g., USR-001)
  2. Follow parent links
  3. Track visited requirements
  4. If you return to the starting requirement, cycle exists

Summary

Key concepts:

  • Cycle: Circular dependency chain in requirement graph
  • Problem: Breaks hierarchy, causes logical impossibility
  • Detection: Depth-first search with path tracking
  • Resolution: Remove links, reverse hierarchy, introduce intermediate requirements

Planned functionality:

  • Automatic cycle detection
  • Detailed cycle reports with suggested fixes
  • Visualization of cyclic paths
  • CI/CD integration
  • Configurable checking

Use cases:

  • CI validation
  • Legacy requirement cleanup
  • Incremental validation

Timeline: Implementation planned for future release

Next Steps

Import and Export

Note: Import and export features are planned but not yet implemented. This chapter describes how these features will work when available.

Import and export enable interoperability with other requirements management tools and formats.

Overview

Planned import/export formats:

  • ReqIF: Requirements Interchange Format (OMG standard)
  • JSON: Machine-readable format for custom tools
  • CSV: Spreadsheet format for analysis
  • Doorstop YAML: Migrate from Doorstop projects
  • HTML: Human-readable export for documentation
  • PDF: Formal document generation

Why Import/Export Matters

Migration: Move requirements from other tools to Requiem

Integration: Exchange requirements with other systems

Analysis: Export to spreadsheets for custom analysis

Documentation: Generate formal requirement documents

Backup: Archive requirements in multiple formats

Compliance: Provide requirements in auditor-requested formats

Export Functionality

Export to JSON

req export --format json --output requirements.json

Output format:

{
  "version": "1",
  "exported_at": "2025-07-22T12:00:00Z",
  "requirements": [
    {
      "hrid": "USR-001",
      "uuid": "4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a",
      "created": "2025-07-22T10:00:00Z",
      "content": "The system shall validate...",
      "tags": ["authentication", "security"],
      "parents": [
        {
          "uuid": "3fc6800c-5acc-457e-baf9-a29b42b663fd",
          "hrid": "USR-002",
          "fingerprint": "e533784ff58c16cbf08e436cb06f09e0..."
        }
      ]
    }
  ]
}

Export to CSV

req export --format csv --output requirements.csv

Output format:

HRID,UUID,Created,Content,Tags,Parents
USR-001,4bfeb7d5-...,2025-07-22T10:00:00Z,"The system shall...","authentication,security","USR-002"
USR-002,3fc6800c-...,2025-07-22T09:00:00Z,"Users shall be able to...","",""
SYS-001,81e63bac-...,2025-07-22T11:00:00Z,"The authentication service...","","USR-001,USR-002"

Open in Excel, Google Sheets, or other spreadsheet tools.

Export to ReqIF

req export --format reqif --output requirements.reqif

ReqIF: OMG standard for requirements exchange, compatible with:

  • IBM DOORS
  • Siemens Polarion
  • PTC Integrity
  • Jama Connect
  • Many other tools

Use case: Send requirements to partners/customers using commercial tools.

Export to HTML

req export --format html --output requirements.html

Features:

  • Styled requirement documents
  • Clickable traceability links
  • Filterable by kind, tag
  • Printable
  • Standalone (no external dependencies)

Export to PDF

req export --format pdf --output requirements.pdf

Use case: Formal requirement documents for:

  • Reviews
  • Approvals
  • Audits
  • Archival

Import Functionality

Import from JSON

req import --format json --input requirements.json

Creates .md files from JSON requirement data.

Validation:

  • Checks for UUID conflicts
  • Validates HRID format
  • Ensures parent references are valid

Conflict resolution:

req import --format json --input requirements.json --on-conflict skip
req import --format json --input requirements.json --on-conflict overwrite
req import --format json --input requirements.json --on-conflict rename

Import from CSV

req import --format csv --input requirements.csv

CSV format requirements:

  • Must have headers: HRID, UUID, Content
  • Optional: Created, Tags, Parents
  • Parents column: comma-separated HRIDs or UUIDs

Example CSV:

HRID,UUID,Content,Tags,Parents
USR-001,4bfeb7d5-...,The system shall validate emails,authentication,
SYS-001,81e63bac-...,Email validation service,authentication,USR-001

Import from Doorstop

Migrate from Doorstop projects:

req import --format doorstop --input /path/to/doorstop/project

What's imported:

  • Doorstop documents → Requiem requirement kinds
  • Doorstop items → Requiem requirements
  • Links → Parent relationships
  • Attributes → Tags or content

Mapping:

Doorstop                  Requiem
--------                  -------
Document PREFIX           Requirement KIND (e.g., USR)
Item UID                  UUID (generated or preserved)
Item text                 Requirement content
Item links                Parent relationships
Item attributes           Tags

Import from ReqIF

req import --format reqif --input requirements.reqif

Use case: Import from commercial tools (DOORS, Polarion, etc.)

Challenges:

  • ReqIF is complex; not all features map to Requiem
  • May require manual cleanup after import

Selective Export/Import

Export Specific Requirements

By kind:

req export --kind USR --format json --output usr-requirements.json

By tag:

req export --tag security --format csv --output security-reqs.csv

By namespace:

req export --namespace AUTH --format html --output auth-reqs.html

Import with Filtering

Skip certain requirements:

req import --format json --input reqs.json --exclude-kind DOC

Rename on import:

req import --format json --input reqs.json --rename-kind USR=USER

Transformation During Import/Export

HRID Remapping

Change HRIDs during import:

req import --format json --input reqs.json --remap-hrids

Generates new HRIDs while preserving UUIDs (maintains traceability).

Use case: Merging requirement sets with conflicting HRIDs.

Namespace Addition

Add namespace during import:

req import --format json --input reqs.json --add-namespace LEGACY

Imports USR-001 as LEGACY-USR-001.

Use case: Integrating acquired projects.

Tag Transformation

Add tags during import:

req import --format json --input reqs.json --add-tag imported --add-tag legacy

Round-Trip Compatibility

Goal: Export and re-import without data loss.

Guaranteed for:

  • JSON format (lossless)
  • ReqIF format (best effort)

Limitations:

  • CSV format (lossy: no complex structures)
  • HTML/PDF (read-only export, no import)

Validation:

# Export
req export --format json --output export.json

# Import to clean directory
mkdir test && cd test
req import --format json --input ../export.json

# Compare
diff -r ../original ./
# Should be identical

Use Cases

Use Case 1: Migrating from Doorstop

Scenario: Existing project using Doorstop.

Goal: Migrate to Requiem.

Workflow:

# Export from Doorstop (if needed)
doorstop export all doorstop-export.json

# Import to Requiem
mkdir requiem-reqs && cd requiem-reqs
req import --format doorstop --input ../doorstop-project

# Validate
req clean

# Compare manually
# Adjust as needed

# Commit
git init
git add .
git commit -m "Migrate from Doorstop to Requiem"

Use Case 2: Exchanging Requirements with Partners

Scenario: Partner uses IBM DOORS; you use Requiem.

Goal: Exchange requirements.

Workflow:

# Export from Requiem to ReqIF
req export --format reqif --output requirements.reqif

# Send to partner
# Partner imports into DOORS

# Receive updated ReqIF from partner
# Import updates
req import --format reqif --input updated-requirements.reqif --on-conflict merge

# Review changes
git diff

# Accept or reject

Use Case 3: Spreadsheet Analysis

Scenario: Need to analyze requirements in Excel.

Goal: Export to CSV, analyze, re-import.

Workflow:

# Export to CSV
req export --format csv --output requirements.csv

# Open in Excel
# Add column "Priority" with values
# Save as requirements-with-priority.csv

# Import with new tags
req import --format csv --input requirements-with-priority.csv \
  --map-column Priority=tag

# Priority values become tags

Use Case 4: Generating Formal Documents

Scenario: Need PDF for customer review.

Goal: Professional requirement document.

Workflow:

# Export to PDF
req export --format pdf --output requirements.pdf \
  --template formal \
  --include-toc \
  --include-traceability

# Review
open requirements.pdf

# Send to customer

Configuration (Planned)

Export Settings

# config.toml (planned)
[export]
# Default export format
default_format = "json"

# Include fingerprints in export
include_fingerprints = true

# Include timestamps
include_timestamps = true

[export.json]
# Pretty-print JSON
pretty = true
indent = 2

[export.csv]
# CSV delimiter
delimiter = ","

# Include header row
include_header = true

[export.pdf]
# Template to use
template = "formal"

# Include table of contents
include_toc = true

# Include traceability matrix
include_traceability = true

Import Settings

[import]
# Action on UUID conflict
on_conflict = "skip"  # skip, overwrite, rename

# Validate after import
validate = true

# Automatically run req clean after import
auto_clean = true

Troubleshooting

UUID Conflicts

Problem: Importing requirements with UUIDs that already exist.

Solutions:

  • --on-conflict skip: Skip conflicting requirements
  • --on-conflict overwrite: Replace existing
  • --on-conflict rename: Generate new UUIDs

Invalid HRIDs

Problem: Imported HRIDs don't match Requiem format.

Solution:

req import --format csv --input reqs.csv --remap-hrids

Generates valid HRIDs automatically.

Problem: Parent references don't resolve.

Diagnosis:

req clean
# Reports missing parent requirements

Solution: Ensure all referenced requirements are imported.

Workarounds (Until Implemented)

Manual export/import with scripts:

Export to JSON (Manual)

#!/usr/bin/env python3
import glob
import yaml
import re
import json

requirements = []
for path in glob.glob("*.md"):
    with open(path) as f:
        content = f.read()
    match = re.match(r'^---\n(.*?)\n---\n(.*)$', content, re.DOTALL)
    if match:
        frontmatter = yaml.safe_load(match.group(1))
        body = match.group(2).strip()
        hrid = path.replace('.md', '')
        requirements.append({
            "hrid": hrid,
            "uuid": frontmatter['uuid'],
            "created": frontmatter['created'],
            "content": body,
            "tags": frontmatter.get('tags', []),
            "parents": frontmatter.get('parents', [])
        })

with open("requirements.json", "w") as f:
    json.dump({"requirements": requirements}, f, indent=2, default=str)

print(f"Exported {len(requirements)} requirements to requirements.json")

Import from CSV (Manual)

#!/usr/bin/env python3
import csv
import uuid
from datetime import datetime

with open("requirements.csv") as f:
    reader = csv.DictReader(f)
    for row in reader:
        hrid = row['HRID']
        req_uuid = row.get('UUID', str(uuid.uuid4()))
        content = row['Content']
        tags = row.get('Tags', '').split(',') if row.get('Tags') else []

        frontmatter = f"""---
_version: '1'
uuid: {req_uuid}
created: {datetime.utcnow().isoformat()}Z
"""
        if tags:
            frontmatter += "tags:\n"
            for tag in tags:
                frontmatter += f"- {tag.strip()}\n"

        frontmatter += "---\n\n"

        with open(f"{hrid}.md", "w") as f:
            f.write(frontmatter + content + "\n")

print("Import complete")

Summary

Planned formats:

  • Export: JSON, CSV, ReqIF, HTML, PDF
  • Import: JSON, CSV, ReqIF, Doorstop

Use cases:

  • Migration from other tools
  • Partner/customer exchange
  • Spreadsheet analysis
  • Formal document generation
  • Backup and archival

Key features:

  • Selective export/import
  • Format transformation
  • Conflict resolution
  • Round-trip compatibility (JSON, ReqIF)
  • Validation

Timeline: Implementation planned for future release

Next Steps

Example: Requiem's Own Requirements

This section contains Requiem's actual project requirements - the specification that defines what this tool does. These requirements serve a dual purpose:

  1. Project Specification: Formal requirements that guide Requiem's development
  2. Worked Example: A real-world demonstration of Requiem managing its own requirements

Why This Matters

Most requirements management tools provide toy examples with a handful of simple requirements. By using Requiem to manage Requiem's own requirements, we demonstrate:

  • Dogfooding: We trust our own tool for serious work
  • Real traceability: User requirements flow down to system requirements
  • Best practices: Professional structure, clear writing, proper linking
  • Scale: A complete requirements set, not just a demo
  • Integration: Requirements living alongside documentation (MdBook)

Requirements Structure

Requiem's requirements follow a two-level hierarchy:

User Requirements (USR)

High-level requirements that describe what users need from the tool. These focus on user-facing functionality and capabilities.

  • USR-001: Plain Text Storage
  • USR-002: Unique and Stable Identifiers
  • USR-003: Requirement Relationships and Traceability
  • USR-004: Graph Analysis and Validation
  • USR-005: Static Site Generator Integration
  • USR-006: Requirement Templates
  • USR-007: Requirement Visibility and Navigation

View all user requirements →

System Requirements (SYS)

Detailed technical requirements that describe how the system implements user needs. These specify file formats, algorithms, CLI commands, and implementation details.

  • SYS-001: Markdown File Format with YAML Frontmatter
  • SYS-002: UUID and HRID Fields
  • SYS-003: Parent Requirement Links
  • ... and 17 more system requirements

View all system requirements →

Traceability in Action

Notice how system requirements trace back to user requirements. For example:

USR-006: Requirement Templates has five child system requirements:

  • SYS-011: Template File Storage
  • SYS-012: Default Template Application
  • SYS-013: Template Override via CLI
  • SYS-014: Template Format
  • SYS-015: Namespace-Specific Templates

This demonstrates the USR→SYS traceability that Requiem was built to support. Each user need is decomposed into specific technical requirements.

Using This as a Learning Resource

As you read through the user guide, refer back to these requirements to see concepts in practice:

  • File Format: See SYS-001 for the actual specification
  • HRIDs: See SYS-002 for identifier format rules
  • Parent Links: See SYS-003 for linking structure
  • Fingerprints: See SYS-005 for suspect link detection
  • Templates: See SYS-011 through SYS-015 for complete template system specification
  • CLI Visibility: See SYS-017 through SYS-019 for the listing and navigation interface

Configuration

This requirements directory includes:

  • config.toml: Requiem configuration (version only)
  • .req/templates/: Template files for new requirements
    • USR.md: Template for user requirements
    • SYS.md: Template for system requirements

Exploring Further

Browse the requirements directly:

Or jump to specific requirements using the links above.


Note: These requirements are managed using Requiem itself. Any changes go through the same review process documented in Maintaining Requirements.

User Requirements

User requirements (USR) define the high-level capabilities that Requiem must provide to its users. These requirements focus on what the tool enables users to accomplish, from the user's perspective.

Overview

Requiem has 7 user requirements that establish the core value proposition:

IDTitleSummary
USR-001Plain Text StorageRequirements stored as plain text files readable in any editor
USR-002Unique and Stable IdentifiersDual identifiers: UUIDs for machines, HRIDs for humans
USR-003Requirement Relationships and TraceabilityParent-child relationships forming traceable hierarchies
USR-004Graph Analysis and ValidationCycle detection and change impact analysis
USR-005Static Site Generator IntegrationCompatibility with MdBook and Sphinx
USR-006Requirement TemplatesSupport for templates when creating new requirements
USR-007Requirement Visibility and NavigationCLI listing and graph exploration for working sets

Detailed Requirements

USR-001: Plain Text Storage

The tool shall store requirements as plain-text files that can be read and edited with any text editor.

Why this matters: Plain text enables version control integration, human review without specialized software, long-term archival, and integration with existing text-based workflows.

Child requirements: SYS-001, SYS-002

Read full requirement →


USR-002: Unique and Stable Identifiers

The tool shall assign each requirement both a UUID (for technical stability) and a human-readable ID/HRID (for human reference).

Why this matters: UUIDs prevent conflicts and enable merging, while HRIDs like "USR-001" make requirements easy to discuss, link, and remember.

Child requirements: SYS-002

Read full requirement →


USR-003: Requirement Relationships and Traceability

The tool shall support defining parent-child relationships between requirements, enabling traceability from high-level needs to detailed specifications.

Why this matters: Traceability is essential for understanding requirement flow, impact analysis, coverage verification, and compliance in regulated industries.

Child requirements: SYS-003

Read full requirement →


USR-004: Graph Analysis and Validation

The tool shall analyze the requirement graph to detect invalid structures (cycles) and identify the impact of changes.

Why this matters: Requirements form a directed acyclic graph (DAG). Cycles are errors. Impact analysis shows what's affected when requirements change.

Child requirements: SYS-004, SYS-005, SYS-008, SYS-009, SYS-010

Read full requirement →


USR-005: Static Site Generator Integration

The tool shall integrate with documentation frameworks (Sphinx, MdBook) so requirements can be included in generated documentation.

Why this matters: Requirements shouldn't live in isolation. They should integrate with design docs, user guides, and API documentation in a single published site.

Child requirements: SYS-006, SYS-007

Read full requirement →


USR-006: Requirement Templates

The tool shall support defining templates that provide default content and structure for new requirements.

Why this matters: Templates ensure consistency, reduce boilerplate, encode best practices, and make requirement creation faster.

Child requirements: SYS-011, SYS-012, SYS-013, SYS-014, SYS-015

Read full requirement →


USR-007: Requirement Visibility and Navigation

The tool shall let users quickly locate, inspect, and summarize requirements from the command line without opening individual files.

Why this matters: Reviewers and systems engineers need instant visibility into requirement sets during audits, change control, and release prep. Native listing and navigation commands eliminate manual grepping and ad-hoc spreadsheets.

Child requirements: SYS-017, SYS-018, SYS-019

Read full requirement →


Traceability

Each USR requirement traces down to one or more SYS (system) requirements that provide technical implementation details:

USR-001 (Plain Text Storage)
  ├── SYS-001 (Markdown File Format with YAML Frontmatter)
  └── SYS-002 (UUID and HRID Fields)

USR-002 (Unique and Stable Identifiers)
  └── SYS-002 (UUID and HRID Fields)

USR-003 (Requirement Relationships and Traceability)
  └── SYS-003 (Parent Requirement Links)

USR-004 (Graph Analysis and Validation)
  ├── SYS-004 (Cycle Detection in Requirement Graph)
  ├── SYS-005 (Suspect Link Detection)
  ├── SYS-008 (Suspect Links CLI Command)
  ├── SYS-009 (Accept Individual Suspect Links)
  └── SYS-010 (Accept All Suspect Links in Bulk)

USR-005 (Static Site Generator Integration)
  ├── SYS-006 (Sphinx and MyST Parser Compatibility)
  └── SYS-007 (MdBook Compatibility)

USR-006 (Requirement Templates)
  ├── SYS-011 (Template File Storage)
  ├── SYS-012 (Default Template Application)
  ├── SYS-013 (Template Override via CLI)
  ├── SYS-014 (Template Format)
  └── SYS-015 (Namespace-Specific Templates)

USR-007 (Requirement Visibility and Navigation)
  ├── SYS-017 (Requirements Listing CLI Command)
  ├── SYS-018 (Listing Filters and Scopes)
  ├── SYS-019 (Relationship Navigation Views)
  └── SYS-020 (Status Dashboard CLI Command)

This hierarchy demonstrates requirement decomposition from user needs down to technical implementation.

Next Steps

System Requirements

System requirements (SYS) define the technical implementation details for Requiem. While user requirements describe what users need, system requirements specify how the tool delivers those capabilities. Some outcomes include dedicated specifications (SPC) that capture detailed interaction or visual design.

Overview

Requiem has 20 system requirements organized by functional area:

File Format & Identifiers

IDTitleParentSummary
SYS-001Markdown File Format with YAML FrontmatterUSR-001Files contain YAML metadata block and Markdown body
SYS-002UUID and HRID FieldsUSR-001, USR-002Frontmatter includes UUID, HRID, version, created timestamp
SYS-003Parent Requirement LinksUSR-003Parent links stored as arrays with UUID, HRID, fingerprint

Graph Analysis & Validation

IDTitleParentSummary
SYS-004Cycle Detection in Requirement GraphUSR-004Tool validates requirements form a DAG with no cycles
SYS-005Suspect Link DetectionUSR-004Detects when parent fingerprint doesn't match stored value
SYS-008Suspect Links CLI CommandUSR-004req suspect command lists all suspect links — spec: SPC-001
SYS-009Accept Individual Suspect LinksUSR-004req accept <child> <parent> updates one suspect link — spec: SPC-001
SYS-010Accept All Suspect Links in BulkUSR-004req accept --all updates all suspect links with safeguards — spec: SPC-001

Static Site Integration

IDTitleParentSummary
SYS-006Sphinx and MyST Parser CompatibilityUSR-005Requirements compatible with Sphinx + MyST Parser
SYS-007MdBook CompatibilityUSR-005Requirements render correctly in MdBook

Template System

IDTitleParentSummary
SYS-011Template File StorageUSR-006Templates stored as markdown files in .req/templates/
SYS-012Default Template ApplicationUSR-006Creating requirement uses template content as default body
SYS-013Template Override via CLIUSR-006-t and -b flags override template content
SYS-014Template FormatUSR-006Templates support full CommonMark markdown
SYS-015Namespace-Specific TemplatesUSR-006Different templates for same KIND with different namespaces

Repository Organisation

IDTitleParentSummary
SYS-016Directory Structure ModesToggle between filename and path-based HRID conventions — spec: SPC-004

CLI Visibility & Navigation

IDTitleParentSummary
SYS-017Requirements Listing CLI CommandUSR-007req list enumerates requirements with key metadata — spec: SPC-002
SYS-018Listing Filters and ScopesUSR-007Filters restrict results by kind, namespace, tags, text — spec: SPC-002
SYS-019Relationship Navigation ViewsUSR-007Options expose parents, children, ancestors, descendants — spec: SPC-002
SYS-020Status Dashboard CLI CommandUSR-007req status shows counts by kind and suspect total — spec: SPC-003

Detailed Requirements

File Format & Identifiers

SYS-001: Markdown File Format with YAML Frontmatter

Each requirement shall be stored as a single plain-text Markdown file containing a YAML frontmatter block and a Markdown body. Files are named {HRID}.md with frontmatter delimited by --- markers.

Read full requirement →


SYS-002: UUID and HRID Fields

The YAML frontmatter shall include required fields: _version (format version), uuid (globally unique identifier), created (ISO 8601 timestamp). The HRID is derived from the filename.

Read full requirement →


Parent links shall be stored in a parents array, where each link contains uuid, hrid, and fingerprint (SHA256 hash of parent content) for change detection.

Read full requirement →


Graph Analysis & Validation

SYS-004: Cycle Detection in Requirement Graph

The tool shall validate that requirements form a directed acyclic graph (DAG). Cycles are invalid because they create circular dependencies. Detection uses depth-first traversal.

Read full requirement →


When a parent's fingerprint doesn't match the stored value in a child's frontmatter, the link is "suspect" - indicating the parent changed. The tool identifies these for review.

Read full requirement →


The req suspect command lists all suspect links in the graph, showing child HRID and suspect parent HRID. Exits with non-zero status if suspect links found (useful for CI).

Read full requirement → Specification: SPC-001


The req accept <child-hrid> <parent-hrid> command accepts a specific suspect link by updating the fingerprint in the child's frontmatter to match the parent's current content hash.

Read full requirement → Specification: SPC-001


The req accept --all command accepts all suspect links in bulk. Supports --dry-run to preview changes and --force to bypass confirmation prompt.

Read full requirement → Specification: SPC-001


Static Site Integration

SYS-006: Sphinx and MyST Parser Compatibility

Requirement files shall be compatible with Sphinx using the MyST Parser, rendering frontmatter as metadata and body content correctly. YAML syntax must be MyST-compatible.

Read full requirement →


SYS-007: MdBook Compatibility

Requirement files shall render correctly in MdBook. YAML frontmatter is ignored (not rendered), and markdown body content displays properly following CommonMark specification.

Read full requirement →


Template System

SYS-011: Template File Storage

Templates are stored as individual markdown files in the .req/templates/ directory, named after requirement kind: {KIND}.md. Namespace-specific templates use {NAMESPACE}-{KIND}.md.

Read full requirement →


SYS-012: Default Template Application

When creating a requirement via req add <KIND>, if a template file exists for that kind, the tool uses the template content as the default body content.

Read full requirement →


SYS-013: Template Override via CLI

The -t/--title and -b/--body flags allow users to override template content. If either flag is provided, the template is completely ignored.

Read full requirement →


SYS-014: Template Format

Template files contain plain markdown text supporting standard markdown formatting: headings, lists, code blocks, links, etc. No special template syntax required - content is inserted verbatim.

Read full requirement →


SYS-015: Namespace-Specific Templates

Different templates can be configured for the same KIND with different namespaces (e.g., AUTH-USR.md vs USR.md). Template lookup tries full prefix first, then falls back to KIND only.

Read full requirement →


Repository Organisation

SYS-016: Directory Structure Modes

Repositories can opt into filename-based or path-based HRID conventions, ensuring teams keep traceability intact while adopting folder structures that fit their workflow.

Read full requirement → Specification: SPC-004


CLI Visibility & Navigation

SYS-017: Requirements Listing CLI Command

The req list command enumerates requirements with key metadata, supporting multiple output formats for human and machine consumption.

Read full requirement → Specification: SPC-002


SYS-018: Listing Filters and Scopes

The listing command provides filters (kind, namespace, tag, text search) and pagination controls so users can focus on relevant subsets.

Read full requirement → Specification: SPC-002


SYS-019: Relationship Navigation Views

Relationship-centric options expose parents, children, ancestors, descendants, and tree views to assist with impact analysis and reviews.

Read full requirement → Specification: SPC-002


SYS-020: Status Dashboard CLI Command

The req status command prints requirement counts per kind, reports the overall total, and highlights the suspect link count with a non-zero exit when attention is required.

Read full requirement → Specification: SPC-003


Implementation Status

Implemented ✅:

  • All file format requirements (SYS-001, SYS-002, SYS-003)
  • Fingerprints and suspect link detection (SYS-005, SYS-008)
  • Static site integration (SYS-006, SYS-007)
  • Complete template system (SYS-011 through SYS-015)
  • Individual suspect link acceptance (SYS-009)
  • Status dashboard command (SYS-020)

In Progress 🚧:

  • Cycle detection (SYS-004)
  • Bulk suspect link acceptance (SYS-010)

Planned 📝:

  • Requirements listing and navigation (SYS-017, SYS-018, SYS-019)

Traceability

Each system requirement traces back to one or more user requirements. See the "Parent" column in the tables above, or view the User Requirements page for the complete traceability tree.

Next Steps

CLI Command Reference

Complete reference for the req command-line interface.

Overview

The req command is the main interface to Requiem. It provides commands for creating, linking, and managing requirements.

Global Synopsis

req [OPTIONS] <COMMAND>

Running req with no subcommand defaults to req status, providing a quick health dashboard for the repository.

Getting Help

# General help
req --help

# Command-specific help
req add --help
req link --help
req clean --help

Version Information

req --version

Global Options

Options that apply to all commands.

-v, --verbose

Increase logging verbosity. Can be specified multiple times.

Levels:

  • No -v: WARN level (errors and warnings only)
  • -v: INFO level (general information)
  • -vv: DEBUG level (detailed debugging information)
  • -vvv: TRACE level (very detailed trace information)

Examples:

req -v clean              # INFO level
req -vv add USR           # DEBUG level
req -vvv link SYS-001 USR-001  # TRACE level

Use cases:

  • Normal use: No -v flag
  • Troubleshooting: -v or -vv
  • Development/debugging: -vvv

-r, --root <PATH>

Specify the root directory containing requirements.

Default: Current directory (.)

Examples:

req --root /path/to/requirements add USR
req -r ./reqs clean
req --root ~/project/requirements link SYS-001 USR-001

Notes:

  • Path can be absolute or relative
  • Must be a directory
  • Directory should contain config.toml (optional) and .md requirement files

Commands

req status

Display a quick summary of requirement counts and suspect links.

Synopsis

req status [OPTIONS]

Options

None.

Behavior

  1. Loads all requirements in the repository.
  2. Prints a table listing each requirement kind with its count and the overall total.
  3. Displays the total number of suspect links.
  4. Exits with status code 1 when any suspect links are present, otherwise 0.

Examples

Summary view:

req status

req add

Create a new requirement.

Synopsis

req add [OPTIONS] <KIND>

Arguments

<KIND> (required)

The kind of requirement to create. This becomes the KIND component of the HRID.

Examples: USR, SYS, SWR, TST, AUTH-USR (with namespace)

Options

-p, --parent <PARENT>...

Specify parent requirement(s) by HRID. Can be specified multiple times or as comma-separated list.

Examples:

# Single parent
req add SYS --parent USR-001

# Multiple parents (multiple flags)
req add SYS --parent USR-001 --parent USR-002

# Multiple parents (comma-separated)
req add SYS --parents USR-001,USR-002

# Short form
req add SYS -p USR-001,USR-002

-t, --title <TITLE>

Set the title of the requirement. The title will be formatted as a markdown heading (# Title).

If both -t and -b are provided, the title appears first, followed by a blank line, then the body.

Examples:

# Create with title only
req add USR -t "User Authentication"

# Create with title and body
req add USR -t "User Authentication" -b "The system shall authenticate users."

-b, --body <BODY>

Set the body content of the requirement. Can be any markdown text.

Examples:

# Create with body only
req add USR -b "The system shall validate user input."

# Create with multi-line body (using quotes)
req add USR -b "The system shall:
- Validate input
- Sanitize data
- Log attempts"

Behavior

  1. Determines next available ID for the given KIND (e.g., USR-001)
  2. Determines title and body:
    • Title from -t/--title flag, or empty if not provided
    • Body from -b/--body flag, or template file, or empty
  3. Creates requirement file <KIND>-<ID>.md with:
    • Level-1 heading with HRID and title (e.g., # USR-001 My Title)
    • YAML frontmatter (UUID, timestamp, tags, parents)
    • Body content (from flag, template, or empty)
  4. Prints the HRID of created requirement

Template Behavior:

  • Templates provide body content only (not HRID or title)
  • CLI flags (-t, -b) always override templates
  • Templates are matched by KIND (e.g., USR.md for USR requirements)
  • Template files are stored in .req/templates/ directory
  • See Templates Guide for details

Examples

Create user requirement:

req add USR
# Output: Added requirement USR-001

Create system requirement with parent:

req add SYS --parent USR-001
# Output: Added requirement SYS-001

Create requirement with multiple parents:

req add SWR --parents SYS-001,SYS-002
# Output: Added requirement SWR-001

Create namespaced requirement:

req add AUTH-USR
# Output: Added requirement AUTH-USR-001

Create with title and body:

req add USR -t "User Authentication" -b "The system shall authenticate users."
# Output: Added requirement USR-001
# Content: # User Authentication\n\nThe system shall authenticate users.

Create with template (assuming .req/templates/USR.md exists):

req add USR
# Output: Added requirement USR-001
# File structure:
# ---
# _version: '1'
# uuid: ...
# created: ...
# ---
# # USR-001
#
# [Template body content from .req/templates/USR.md]

Create with template and title:

req add USR -t "User Authentication"
# Output: Added requirement USR-001
# Uses title from -t flag, body from template

Override template with body flag:

req add USR -b "Custom content"
# Output: Added requirement USR-001
# Uses body from -b flag, template ignored

Error Cases

Empty KIND:

req add ""
# Error: Kind cannot be empty

Invalid KIND (if allowed_kinds configured):

req add INVALID
# Error: Kind 'INVALID' is not in the allowed list

Parent not found:

req add SYS --parent USR-999
# Error: Parent requirement USR-999 not found

Create a parent-child link between two existing requirements.

Synopsis

req link <CHILD> <PARENT>

Arguments

<CHILD> (required)

HRID of the child requirement (the requirement gaining a parent).

<PARENT> (required)

HRID of the parent requirement (the upstream requirement).

Behavior

  1. Loads both child and parent requirements
  2. Adds parent reference to child's frontmatter:
    • Parent's UUID
    • Parent's current HRID
    • Parent's current fingerprint
  3. Saves updated child requirement
  4. Prints confirmation message

Examples

Link system to user requirement:

req link SYS-001 USR-001
# Output: Linked SYS-001 to USR-001

Link with namespaces:

req link AUTH-SYS-001 AUTH-USR-001
# Output: Linked AUTH-SYS-001 to AUTH-USR-001

Create second parent (multiple parents supported):

req link SYS-001 USR-001  # First parent
req link SYS-001 USR-002  # Second parent
# SYS-001 now has two parents

Error Cases

Child not found:

req link SYS-999 USR-001
# Error: Child requirement SYS-999 not found

Parent not found:

req link SYS-001 USR-999
# Error: Parent requirement USR-999 not found

Invalid HRID format:

req link INVALID USR-001
# Error: Invalid HRID format: INVALID

req suspect

List all suspect links in the requirement graph.

Synopsis

req suspect

Arguments

None.

Options

None.

Behavior

  1. Loads all requirements from the requirements directory
  2. Compares stored parent fingerprints with current parent fingerprints
  3. Lists all requirements with mismatched fingerprints (suspect links)
  4. For each suspect link, displays:
    • Child HRID → Parent HRID
    • Stored fingerprint (first 16 characters)
    • Current fingerprint (first 16 characters)
  5. Exits with code 1 if suspect links found (useful for CI/CD)
  6. Exits with code 0 if no suspect links found

Examples

Check for suspect links:

req suspect

Example output when suspect links exist:

Found 3 suspect link(s):

  SYS-001 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

  SYS-002 → USR-001
    Stored fingerprint:  e533784ff58c16cb
    Current fingerprint: c4020419ead000e9

  SYS-005 → USR-004
    Stored fingerprint:  407c6e3413d5b3fa
    Current fingerprint: c28afe188a974322

Example output when no suspect links:

No suspect links found.

In CI/CD pipeline:

req suspect && echo "All links current" || echo "Review needed"

Use Cases

  • Pre-commit validation: Check if parent requirements changed without updating children
  • CI/CD integration: Fail builds when requirements need review
  • Regular audits: Identify requirements needing review after upstream changes
  • Change impact: See which requirements are affected by parent changes

Exit Codes

  • 0: No suspect links found (all fingerprints current)
  • 1: Suspect links found (some requirements need review)

This exit code behavior makes the command useful in automation:

#!/bin/bash
req suspect
if [ $? -ne 0 ]; then
    echo "ERROR: Requirements need review before release"
    exit 1
fi

req accept

Accept suspect links after review, updating fingerprints to current values.

Synopsis

req accept <CHILD> <PARENT>
req accept --all

Arguments

<CHILD> (required unless --all)

HRID of the child requirement containing the suspect link.

<PARENT> (required unless --all)

HRID of the parent requirement referenced by the suspect link.

Options

--all

Accept all suspect links in the requirements directory. Updates all fingerprints to match current parent values.

Behavior

Single link mode (req accept <CHILD> <PARENT>):

  1. Loads the child and parent requirements
  2. Verifies the link exists
  3. Updates the stored fingerprint to match the parent's current fingerprint
  4. Saves the updated child requirement
  5. Prints confirmation or reports if link was already up to date

Bulk mode (req accept --all):

  1. Finds all suspect links
  2. Updates all fingerprints to current values
  3. Saves all affected requirements
  4. Prints summary of updated links

Examples

Accept a single suspect link:

req accept SYS-001 USR-001
# Output: Accepted suspect link: SYS-001 → USR-001

Accept all suspect links:

req accept --all
# Output:
# Accepted 3 suspect link(s):
#   SYS-001 → USR-001
#   SYS-002 → USR-001
#   SYS-005 → USR-004

Accept after no review needed:

req accept SYS-001 USR-001
# Output: Link SYS-001 → USR-001 is already up to date (not suspect).

Workflow

Typical workflow for handling suspect links:

# 1. Check for suspect links
req suspect

# 2. Review parent changes
vim USR-001.md  # Review what changed

# 3. Review child requirement
vim SYS-001.md  # Update if needed

# 4. Accept the link (marks as reviewed)
req accept SYS-001 USR-001

# 5. Verify no more suspect links
req suspect

Use Cases

  • After review: Mark requirements as reviewed after verifying consistency with parent changes
  • Bulk acceptance: Update all fingerprints after reviewing multiple changes
  • Post-merge: Accept fingerprints after merging upstream requirement changes
  • Release preparation: Clear all suspect links before release

Error Cases

Link not found:

req accept SYS-001 USR-999
# Error: Parent requirement USR-999 not found

Child not found:

req accept SYS-999 USR-001
# Error: Child requirement SYS-999 not found

No link exists:

req accept SYS-001 USR-001
# Error: link from SYS-001 to USR-001 not found

No suspect links with --all:

req accept --all
# Output: No suspect links to accept.

req list

List requirements with optional filtering, traversal, and output formatting.

Synopsis

req list [OPTIONS] [HRID...]

Arguments

<HRID> (optional, repeats)

Target requirements to anchor the listing. When omitted, the command starts from all requirements (with the default view limited to top-level, parentless requirements).

Options

  • --columns <COL>: Comma-separated list of columns (hrid, title, kind, namespace, parents, children, tags, path, created). Default columns show HRID, title, kind, parent count, child count, and tags. When --quiet is present without explicit columns, only HRIDs are emitted.
  • --sort <FIELD>: Sort output by hrid (default), kind, title, or created.
  • --output <FORMAT>: Choose table (default), json, or csv. Table output is human readable; JSON and CSV are machine friendly.
  • --quiet: Suppress headers and format rows for shell pipelines. Defaults to one HRID per line unless additional columns are requested.
  • --kind <KIND>, --namespace <SEG>, --tag <TAG>: Filter by kind, namespace segment, or tag (case-insensitive, commas or repeated flags allowed).
  • --orphans, --leaves: Limit to requirements with no parents or no children.
  • --contains <TEXT>, --regex <PATTERN>: Search requirement title/body with a case-insensitive substring or Rust regular expression (mutually exclusive).
  • --view <MODE>: Choose how to explore relationships. Options: summary (default table), parents, children, ancestors, descendants, tree (indented descendant view), and context (base rows plus labelled neighbours).
  • --depth <N>: Depth limit for the selected view (default 1 for parents/children/context, unlimited for ancestors/descendants/tree). Use 0 for no limit.
  • --limit <N>, --offset <N>: Paginate large result sets by skipping offset rows and then truncating to limit. Defaults to 200 rows when omitted; pass --limit 0 for no cap.

Behavior

  1. Loads all requirements and builds parent/child relationships.
  2. Determines the working set:
    • If HRIDs are provided, they anchor traversal; otherwise all requirements are considered.
    • Without explicit filters or traversal flags, the default view lists every requirement sorted by HRID and capped at the default limit.
  3. Applies requested filters and relationship traversal.
  4. Formats output according to the selected layout.

Examples

Top-level overview:

req list
HRID     Title                              Kind  Parents  Children  Tags
USR-001  Plain Text Storage                 USR   0        2         
USR-004  Graph Analysis and Validation      USR   0        5         

Filter by kind and tag:

req list --kind SYS --tag navigation --output csv

Descendants of a user requirement:

req list USR-004 --view descendants --kind SYS

Tree view:

req list USR-004 --view tree --depth 2

req clean

Correct parent HRIDs in all requirements.

Synopsis

req clean

Arguments

None.

Options

None.

Behavior

  1. Loads all requirements from the requirements directory
  2. For each requirement:
    • Checks parent HRIDs against actual parent filenames
    • If HRID is outdated, updates to current HRID
    • Saves requirement if changed
  3. Silent on success (no output if no corrections made)
  4. With -v, logs each correction

Examples

Validate/correct all requirements:

req clean
# (no output = success, all HRIDs correct or corrected)

Verbose output:

req -v clean
# Output:
# INFO Corrected parent HRID in SYS-001: USR-001 → USR-100
# INFO Corrected parent HRID in SYS-002: USR-001 → USR-100

With custom root:

req --root /path/to/requirements clean

Use Cases

  • After renaming requirement files
  • After reorganizing requirements
  • Before committing changes (validation)
  • Regular maintenance

Error Cases

Parent UUID not found:

req clean
# Error: Parent requirement <UUID> not found!

This indicates a requirement references a parent that doesn't exist. Either restore the parent or manually remove the reference.

Self-referential parent:

req clean
# Error: Requirement <UUID> is its own parent!

This indicates a requirement lists itself as a parent. Manually remove the self-reference.

Common Workflows

Creating a Requirement Hierarchy

# Create user requirements
req add USR  # USR-001
req add USR  # USR-002

# Create system requirements linked to user requirements
req add SYS --parent USR-001  # SYS-001
req add SYS --parent USR-002  # SYS-002

# Create software requirement satisfying multiple system requirements
req add SWR --parents SYS-001,SYS-002  # SWR-001

# Create test linked to software requirement
req add TST --parent SWR-001  # TST-001

Renaming Requirements

# Rename requirement file
mv USR-001.md USR-100.md

# Update parent references
req clean

# Verify
git diff  # See updated parent HRIDs

Linking Existing Requirements

# Requirements already exist
# USR-001.md
# SYS-001.md

# Create link
req link SYS-001 USR-001

# Add second parent
req link SYS-001 USR-002

Managing Requirement Changes

# Edit a parent requirement
vim USR-001.md  # Make changes

# Check for suspect links
req suspect
# Output: SYS-001 → USR-001 (fingerprint mismatch)

# Review affected child
vim SYS-001.md  # Review and update if needed

# Accept the change
req accept SYS-001 USR-001

# Verify all links current
req suspect
# Output: No suspect links found.

Bulk Review Workflow

# After updating multiple parent requirements
req suspect
# Shows all suspect links

# Review and update children as needed
vim SYS-001.md
vim SYS-002.md
# ... review all affected requirements

# Accept all at once
req accept --all

# Commit changes
git add -A
git commit -m "Update requirements after USR changes"

Exit Codes

Requiem uses standard exit codes:

  • 0: Success
  • Non-zero: Error

Examples:

req add USR && echo "Success"  # Success
req add INVALID || echo "Failed"  # Failed (if KIND not allowed)

Use in scripts:

#!/bin/bash
req clean
if [ $? -eq 0 ]; then
    echo "Requirements validated"
    git commit -am "Update requirements"
else
    echo "Validation failed"
    exit 1
fi

Environment Variables

RUST_LOG

Control logging level (alternative to -v flags).

Values:

  • error: Error messages only
  • warn: Warnings and errors (default)
  • info: Informational messages
  • debug: Debug messages
  • trace: Verbose trace messages

Examples:

RUST_LOG=info req clean
RUST_LOG=debug req add USR
RUST_LOG=trace req link SYS-001 USR-001

Module-specific logging:

RUST_LOG=requiem=debug req clean
RUST_LOG=requiem::storage=trace req add USR

Output Formats

Standard Output

Success messages go to stdout:

req add USR
# Output: Added requirement USR-001

Standard Error

Errors and logs go to stderr:

req add INVALID 2> errors.log

JSON Output (Planned)

Machine-readable output:

req add USR --format json
# {"success": true, "hrid": "USR-001", "uuid": "..."}

Shell Completion

Generate shell completion scripts:

Bash:

req --generate-completion bash > /etc/bash_completion.d/req

Zsh:

req --generate-completion zsh > /usr/local/share/zsh/site-functions/_req

Fish:

req --generate-completion fish > ~/.config/fish/completions/req.fish

PowerShell:

req --generate-completion powershell > req.ps1

(Note: Completion generation not yet implemented in current version)

Configuration File

While not a CLI option, the config.toml file affects CLI behavior:

_version = "1"
allowed_kinds = ["USR", "SYS", "TST"]  # Restricts req add
digits = 3                              # Affects HRID formatting
allow_unrecognised = true               # Affects req clean behavior

See Configuration Reference for details.

Performance Considerations

Parallel Loading

Requiem loads requirements in parallel for performance:

  • 100 requirements: < 1 second
  • 1000 requirements: ~2-3 seconds
  • 10000 requirements: ~15-20 seconds

Large Directories

For very large requirement sets (1000+):

  • Use subdirectories for organization
  • req clean scales well due to parallelism
  • Consider namespaces to partition large sets

Troubleshooting

Command Not Found

Error: req: command not found

Solution:

# Install Requiem
cargo install requirements-manager

# Verify installation
which req
req --version

Permission Denied

Error: Permission denied when creating/modifying files

Solution: Ensure write permissions to requirements directory:

chmod u+w *.md
chmod u+w .

Invalid Configuration

Error: Failed to parse config file

Solution: Check config.toml syntax:

# Validate TOML
cat config.toml | python -c "import sys, toml; toml.load(sys.stdin)"

Unexpected Behavior

Enable verbose logging:

req -vv <command>

Check logs for detailed error messages.

Summary

Core commands:

  • req add <KIND> - Create requirement
  • req link <CHILD> <PARENT> - Link requirements
  • req suspect - List suspect links (fingerprint mismatches)
  • req accept <CHILD> <PARENT> - Accept suspect link after review
  • req accept --all - Accept all suspect links
  • req clean - Correct parent HRIDs

Global options:

  • -v, --verbose - Increase logging
  • -r, --root <PATH> - Specify requirements directory

Exit codes:

  • 0 - Success
  • 1 - Suspect links found (req suspect only)
  • Non-zero - Error (other commands)

Getting help:

  • req --help - General help
  • req <command> --help - Command-specific help

Next Steps

File Format Specification

Formal specification of the Requiem requirement file format.

Overview

Requiem requirements are stored as Markdown files with YAML frontmatter. This document provides the formal specification.

File Extension

.md (Markdown)

Character Encoding

UTF-8

Filename Format

{NAMESPACE-}*{KIND}-{ID}.md

Where:

  • NAMESPACE: Zero or more namespace segments (alphanumeric, hyphen-separated)
  • KIND: Alphanumeric requirement kind (e.g., USR, SYS)
  • ID: Positive integer (zero-padded to configured digits, default 3)

Examples:

USR-001.md
SYS-042.md
AUTH-USR-001.md
MOBILE-AUTH-LOGIN-SYS-005.md

Validation Rules:

  • Must end with .md
  • NAMESPACE segments: non-empty, alphanumeric plus hyphen
  • KIND: non-empty, alphanumeric
  • ID: positive integer (1 or more), may have leading zeros
  • Segments separated by single hyphen -
  • No consecutive hyphens --
  • No leading or trailing hyphens

File Structure

Requirements consist of three parts:

  1. YAML Frontmatter: Metadata enclosed in --- delimiters
  2. HRID Heading: First heading with HRID as first token
  3. Markdown Body: Requirement text in CommonMark format

General Structure

---
<YAML frontmatter>
---
# <HRID> <Title>
<blank line optional>
<Markdown content>

Example

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
tags:
- authentication
- security
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
---
# SYS-001 Email Validation

The system shall validate user email addresses according to RFC 5322.

Email validation must occur before account creation.

YAML Frontmatter

Delimiters

  • Opening delimiter: --- on first line
  • Closing delimiter: --- on its own line
  • Both required

Schema Version 1

Current version: 1

Required Fields

_version

Type: String (quoted)

Format: "1"

Purpose: Schema version for forward/backward compatibility

Validation:

  • Must be present
  • Must be string type (quoted in YAML)
  • Currently only "1" is valid

Example:

_version: '1'
uuid

Type: UUID (string format)

Format: UUID v4 (RFC 4122)

Purpose: Globally unique, stable identifier

Validation:

  • Must be present
  • Must be valid UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • Should be generated with uuid::Uuid::new_v4() or equivalent
  • Must be unique across all requirements (globally)
  • Must never change after creation

Example:

uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created

Type: Timestamp (string format)

Format: ISO 8601 with timezone (RFC 3339)

Purpose: Requirement creation timestamp

Validation:

  • Must be present
  • Must be valid ISO 8601 timestamp
  • Must include timezone (use UTC: Z suffix)
  • Format: YYYY-MM-DDTHH:MM:SS.sssssssssZ

Example:

created: 2025-07-22T12:19:56.950194157Z

Notes:

  • Nanosecond precision supported
  • Timezone must be UTC (Z suffix)
  • Set once at creation; never modified

Optional Fields

tags

Type: Array of strings

Format: YAML list

Purpose: Categorize and tag requirements

Validation:

  • Optional (omit if no tags)
  • Array elements must be strings
  • Empty array allowed but should be omitted
  • No duplicate tags within same requirement
  • Tags are case-sensitive

Example:

tags:
- authentication
- security
- high-priority

Omission:

# No tags field = no tags
_version: '1'
uuid: ...
# tags field omitted

Serialization:

  • Include only if non-empty: skip_serializing_if = "BTreeSet::is_empty"
  • Stored as BTreeSet internally (sorted, unique)
parents

Type: Array of parent objects

Format: YAML list of objects

Purpose: Link to parent (upstream) requirements

Validation:

  • Optional (omit if no parents, e.g., root requirements)
  • Array elements must be parent objects (see Parent Object Schema)
  • Empty array allowed but should be omitted
  • Duplicate parent UUIDs allowed (though unusual)

Example:

parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
- uuid: 7a8f9e2b-1c3d-4e5f-6a7b-8c9d0e1f2a3b
  fingerprint: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
  hrid: USR-003

Omission:

# No parents field = no parents (root requirement)
_version: '1'
uuid: ...
# parents field omitted

Serialization:

  • Include only if non-empty: skip_serializing_if = "Vec::is_empty"

Parent Object Schema

Each parent object has three fields:

uuid

Type: UUID (string format)

Format: UUID v4

Purpose: Stable reference to parent requirement

Validation:

  • Must be present in parent object
  • Must be valid UUID format
  • Should match uuid field of an existing requirement

Example:

uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
fingerprint

Type: String (hex-encoded SHA256 hash)

Format: 64-character hexadecimal string

Purpose: Content hash of parent for change detection

Validation:

  • Must be present in parent object
  • Must be 64-character hexadecimal string
  • Generated by hashing parent's content and tags with SHA256

Example:

fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356

Generation:

1. Collect parent's content (markdown body) and tags
2. Serialize with Borsh encoding
3. Hash with SHA256
4. Encode as hexadecimal string (64 characters)
hrid

Type: String (HRID format)

Format: {NAMESPACE-}*{KIND}-{ID}

Purpose: Human-readable reference to parent (convenience field)

Validation:

  • Must be present in parent object
  • Must be valid HRID format
  • Should match parent's filename (without .md extension)

Example:

hrid: USR-001

Notes:

  • Convenience field for human readability
  • May become outdated if parent is renamed
  • Corrected by req clean command
  • UUID is authoritative; HRID is informational

Schema Evolution

Future schema versions (e.g., _version: "2") will be backward-compatible:

  • New optional fields may be added
  • Required fields will not be removed
  • Field semantics will not change incompatibly

Parsers should:

  • Ignore unknown fields
  • Provide defaults for missing optional fields
  • Reject unknown _version values (fail-safe)

HRID Heading

Format

The first heading in the markdown must contain the HRID as the first token:

# <HRID> <Title Text>

Requirements

  • Must be a level-1 heading (#)
  • HRID must be the first token (word)
  • Followed by space and title text
  • HRID must match the filename (without .md)

Examples

# USR-001 Plain Text Storage
# SYS-042 Email Validation System
# AUTH-LOGIN-SYS-001 Password Hashing

Rationale

The HRID is stored in the heading (not frontmatter) for compatibility with Sphinx and MdBook, which use the first heading as the page title.

Markdown Body

Format

CommonMark (Markdown specification)

Location

Everything after the first heading is the markdown body.

Content

Free-form Markdown:

  • Headings (##, ###, etc. - first # is reserved for HRID)
  • Paragraphs
  • Lists (ordered, unordered)
  • Code blocks (fenced, indented)
  • Emphasis (bold, italic)
  • Links
  • Images
  • Blockquotes
  • Tables
  • Any CommonMark-compliant content

Whitespace

  • Leading/trailing whitespace: preserved
  • Empty lines between frontmatter and body: ignored
  • Empty body: valid (empty string)

Example

---
_version: '1'
uuid: ...
created: ...
---
# USR-001 Email Validation

The system shall validate user email addresses.

## Rationale

Email validation ensures...

## Acceptance Criteria

- Valid email format
- Rejects invalid emails
- Provides clear error messages

Parsing Rules

Frontmatter Parsing

  1. First line must be ---
  2. Read lines until next --- on its own line
  3. Parse collected lines as YAML
  4. Validate against schema
  5. Remaining lines are markdown body

Error Handling

Missing opening delimiter:

Error: Expected frontmatter starting with '---'

Missing closing delimiter:

Error: Unexpected EOF while parsing frontmatter

Invalid YAML:

Error: Failed to parse YAML: <syntax error details>

Missing required field:

Error: Missing required field '<field_name>'

Invalid UUID format:

Error: Invalid UUID format: '<value>'

Invalid timestamp format:

Error: Invalid timestamp format: '<value>'

Unknown _version:

Error: Unknown schema version: '<value>'

Strict vs. Permissive

Requiem parsing is strict by default:

  • All required fields must be present
  • All fields must be valid
  • Unknown fields in schema version 1 cause errors (currently)

Controlled by allow_invalid config option:

  • allow_invalid = false (default): Strict parsing, fail on errors
  • allow_invalid = true: Skip invalid requirements with warnings

Serialization Rules

Field Order

Fields serialized in this order:

  1. _version
  2. uuid
  3. created
  4. tags (if present)
  5. parents (if present)

Omission Rules

  • tags: Omitted if empty
  • parents: Omitted if empty

Formatting

  • YAML indentation: 2 spaces
  • String quoting: Single quotes for strings containing special characters
  • Array formatting: One element per line with - prefix
  • Object formatting: Indented key-value pairs

Example Output

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
tags:
- authentication
- security
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
---

Requirement text here.

Validation

Syntactic Validation

  • Valid YAML frontmatter
  • Valid Markdown body (CommonMark)
  • Correct delimiters

Semantic Validation

  • Required fields present
  • Field types correct
  • UUID format valid
  • Timestamp format valid
  • HRID format valid (in parent references)
  • Fingerprint format valid (64-char hex)

Referential Integrity

  • Parent UUIDs reference existing requirements
  • No self-references (requirement is not its own parent)
  • No duplicate UUIDs across all requirements

Configuration-Based Validation

  • HRID KIND in allowed_kinds (if configured)
  • File follows naming convention (if allow_unrecognised = false)

Canonical Example

---
_version: '1'
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
created: 2025-07-22T12:19:56.950194157Z
tags:
- authentication
- security
- high-priority
parents:
- uuid: 3fc6800c-5acc-457e-baf9-a29b42b663fd
  fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
  hrid: USR-001
- uuid: 7a8f9e2b-1c3d-4e5f-6a7b-8c9d0e1f2a3b
  fingerprint: a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456
  hrid: USR-003
---
# SYS-001 Email Validation

The system shall validate user email addresses according to RFC 5322.

## Rationale

Email validation ensures that user accounts can be contacted and that
authentication tokens can be delivered reliably.

## Acceptance Criteria

- Email addresses must match RFC 5322 format
- Invalid email addresses must be rejected with clear error message
- Validation must occur before account creation

## References

- RFC 5322: Internet Message Format
- OWASP Email Validation Guidelines

Summary

File format:

  • Markdown (.md) files with UTF-8 encoding
  • YAML frontmatter enclosed in --- delimiters
  • CommonMark markdown body

Required frontmatter fields:

  • _version: Schema version (currently "1")
  • uuid: Unique identifier (UUID v4)
  • created: Creation timestamp (ISO 8601 with UTC)

Optional frontmatter fields:

  • tags: Array of tags
  • parents: Array of parent objects (uuid, fingerprint, hrid)

Validation:

  • Strict by default
  • Controlled by allow_invalid config option
  • Includes syntactic, semantic, and referential checks

Next Steps

Configuration Reference

Complete reference for Requiem's config.toml configuration file.

Overview

The config.toml file configures Requiem's behavior. It must be located in the root of your requirements directory.

File Location

requirements/
├── config.toml    ← Configuration file
├── USR-001.md
├── USR-002.md
└── SYS-001.md

File Format

TOML (Tom's Obvious Minimal Language)

Optional

Configuration file is optional. If absent, Requiem uses defaults.

Schema Version 1

Current schema version: 1

Complete Example

_version = "1"
allowed_kinds = ["USR", "SYS", "SWR", "TST"]
digits = 3
allow_unrecognised = false
allow_invalid = false
subfolders_are_namespaces = false

Configuration Fields

_version (required)

Schema version for forward/backward compatibility.

Type: String (quoted)

Required: Yes

Default: N/A (must be explicitly specified)

Valid Values: "1"

Example:

_version = "1"

Purpose:

  • Enables future schema changes
  • Allows old Requiem versions to detect incompatible configs
  • Allows new Requiem versions to handle old configs

Validation:

  • Must be present
  • Must be quoted string
  • Must be "1" in current version

Errors:

Missing:

# config.toml
allowed_kinds = ["USR"]
Error: Failed to parse config file: missing field '_version'

Wrong type:

_version = 1  # Wrong: integer instead of string
Error: Failed to parse config file: invalid type: integer, expected a string

allowed_kinds

Restrict which requirement kinds are permitted.

Type: Array of strings

Required: No

Default: [] (empty array = all kinds allowed)

Valid Values: Array of non-empty strings

Example:

allowed_kinds = ["USR", "SYS", "SWR", "TST"]

Purpose:

  • Enforce project conventions
  • Prevent typos (USR vs UST)
  • Document allowed requirement types

Behavior:

Empty array (default):

allowed_kinds = []
# OR omit field entirely

All kinds accepted: USR-001, SYS-001, CUSTOM-001, etc.

Non-empty array:

allowed_kinds = ["USR", "SYS"]

Only listed kinds accepted:

  • req add USR ✓ Succeeds
  • req add SYS ✓ Succeeds
  • req add TST ✗ Fails (TST not in allowed list)

With namespaces:

allowed_kinds = ["AUTH-USR", "AUTH-SYS", "PAYMENT-USR"]

Exact match required:

  • req add AUTH-USR ✓ Succeeds
  • req add USR ✗ Fails (USR not in allowed list)

Examples:

Aerospace project (DO-178C):

allowed_kinds = ["URQT", "SRQT", "SWRQT", "HWRQT", "TRQT"]

Software project:

allowed_kinds = ["USR", "SYS", "SWR", "TST", "DOC"]

Multi-component with namespaces:

allowed_kinds = [
    "AUTH-USR", "AUTH-SYS",
    "PAYMENT-USR", "PAYMENT-SYS",
    "REPORTING-USR", "REPORTING-SYS"
]

Validation:

  • Each element must be non-empty string
  • Duplicates allowed (but pointless)
  • Case-sensitive matching

Errors:

Empty string in array:

allowed_kinds = ["USR", ""]
Error: Failed to parse config file: empty strings not allowed in allowed_kinds

digits

Number of digits in HRID numbering (with zero-padding).

Type: Unsigned integer

Required: No

Default: 3

Valid Values: Any positive integer (typically 3-5)

Example:

digits = 3

Purpose:

  • Control HRID formatting
  • Accommodate projects with many requirements per kind

Behavior:

digits = 3 (default):

USR-001
USR-002
USR-010
USR-099
USR-100  # Expands beyond 3 digits when needed
USR-1000

digits = 4:

USR-0001
USR-0002
USR-0010
USR-0999
USR-1000
USR-10000  # Expands beyond 4 digits when needed

digits = 2:

USR-01
USR-02
USR-99
USR-100  # Expands beyond 2 digits when needed

Parsing:

  • Requirements can have any number of digits when parsing
  • USR-1, USR-01, USR-001 all parse as ID 1
  • Display/creation uses configured padding

Recommendations:

  • digits = 3: < 1000 requirements per kind (most projects)
  • digits = 4: 1000-9999 requirements per kind
  • digits = 5: Very large projects

Examples:

Small project:

digits = 2

Medium project (default):

digits = 3

Large project:

digits = 4

Validation:

  • Must be positive integer
  • Zero or negative not allowed

Errors:

Zero:

digits = 0
Error: Failed to parse config file: digits must be positive

allow_unrecognised

Allow markdown files that don't match HRID pattern.

Type: Boolean

Required: No

Default: false

Valid Values: true, false

Example:

allow_unrecognised = true

Purpose:

  • Enable mixing requirements with other documentation
  • Control strictness of file validation

Behavior:

allow_unrecognised = false (default, strict):

docs/
├── config.toml
├── USR-001.md     ← Loaded (valid HRID)
├── USR-002.md     ← Loaded (valid HRID)
└── README.md      ← ERROR: Not a valid HRID

Error during req clean:

Error: Unrecognised file: README.md

allow_unrecognised = true (permissive):

docs/
├── config.toml
├── USR-001.md     ← Loaded (valid HRID)
├── USR-002.md     ← Loaded (valid HRID)
└── README.md      ← Ignored (not a valid HRID)

No error; README.md is silently skipped.

Use Cases:

Use false (default):

  • Dedicated requirements directory
  • Strict validation desired
  • Catch typos in filenames

Use true:

  • Requirements mixed with MdBook/Sphinx content
  • Documentation and requirements in same directory
  • Legacy projects with existing non-requirement files

Examples:

Strict requirements-only:

_version = "1"
allow_unrecognised = false

Mixed documentation:

_version = "1"
allow_unrecognised = true  # Allow chapter1.md, README.md, etc.

Validation:

  • Must be boolean
  • Case-sensitive: true or false (lowercase)

Errors:

Wrong case:

allow_unrecognised = True  # Wrong: uppercase
Error: Failed to parse config file: invalid value

subfolders_are_namespaces

Control whether subfolder paths contribute to requirement namespaces.

Type: Boolean

Required: No

Default: false

Valid Values: true, false

Example:

subfolders_are_namespaces = true

Purpose:

  • Choose between filename-based and path-based directory organization
  • Enable cleaner filenames in hierarchical structures
  • Align folder structure with namespace hierarchy

Behavior:

subfolders_are_namespaces = false (default, filename-based):

requirements/
├── custom/folder/
│   └── system-auth-REQ-001.md   → HRID: system-auth-REQ-001
└── any/path/
    └── payment-USR-002.md       → HRID: payment-USR-002
  • HRID: Fully encoded in filename
  • Folders: Purely organizational, don't affect HRID
  • Flexibility: Move files freely without changing HRIDs

subfolders_are_namespaces = true (path-based):

requirements/
├── system/
│   └── auth/
│       ├── REQ-001.md           → HRID: system-auth-REQ-001
│       └── USR/
│           └── 002.md           → HRID: system-auth-USR-002
└── payment/
    └── USR-003.md               → HRID: payment-USR-003
  • HRID: Namespace from folder path + KIND-ID from filename
  • Folders: Encode namespace segments
  • Format inference:
    • Numeric filename (002.md) → KIND from parent folder
    • KIND-ID filename (USR-003.md) → KIND from filename
  • Constraint: Moving files changes their HRID

Use Cases:

Use false (default):

  • Maximum folder flexibility
  • Arbitrary organizational schemes
  • Frequent folder reorganization
  • Explicit namespaces in every filename

Use true:

  • Hierarchical component structures
  • Folder structure mirrors system architecture
  • Cleaner, shorter filenames
  • Enforced namespace-folder alignment

Examples:

Filename-based (flexible organization):

_version = "1"
subfolders_are_namespaces = false

Path-based (structured hierarchy):

_version = "1"
subfolders_are_namespaces = true

Migration:

To convert from filename-based to path-based:

  1. Set subfolders_are_namespaces = true
  2. Reorganize files to match namespace structure
  3. Rename files to remove namespace prefix

To convert from path-based to filename-based:

  1. Move files and encode full HRID in filename
  2. Set subfolders_are_namespaces = false
  3. Optionally flatten directory structure

See Directory Structure for detailed migration guide.

Validation:

  • Must be boolean
  • Case-sensitive: true or false (lowercase)

Errors:

Wrong type:

subfolders_are_namespaces = "yes"  # Wrong: string instead of boolean
Error: Failed to parse config file: invalid type: string, expected a bool

allow_invalid

Allow requirements with invalid YAML frontmatter or formatting.

Type: Boolean

Required: No

Default: false

Valid Values: true, false

Example:

allow_invalid = true

Purpose:

  • Control strictness of requirement validation
  • Enable partial loading during migration or recovery

Behavior:

allow_invalid = false (default, strict):

requirements/
├── USR-001.md    ← Valid frontmatter, loaded
├── USR-002.md    ← Invalid frontmatter (missing uuid)
└── USR-003.md    ← Valid frontmatter

Error during req clean:

Error: Invalid requirement USR-002.md: missing required field 'uuid'

Loading fails; no requirements processed.

allow_invalid = true (permissive):

requirements/
├── USR-001.md    ← Valid, loaded
├── USR-002.md    ← Invalid, skipped with warning
└── USR-003.md    ← Valid, loaded

Warning during req clean:

Warning: Skipping invalid requirement USR-002.md: missing required field 'uuid'
Successfully loaded 2 requirements (1 skipped)

Loading continues; valid requirements processed.

Use Cases:

Use false (default):

  • Production use
  • Ensure data quality
  • Catch errors immediately

Use true:

  • Migrating from another tool (gradual fix-up)
  • Recovering from manual editing errors
  • Development/debugging
  • Partial validation during cleanup

Examples:

Production (strict):

_version = "1"
allow_invalid = false

Migration (permissive):

_version = "1"
allow_invalid = true  # Temporarily allow invalid requirements

Validation:

  • Must be boolean
  • Case-sensitive: true or false (lowercase)

Errors:

Wrong type:

allow_invalid = "yes"  # Wrong: string instead of boolean
Error: Failed to parse config file: invalid type: string, expected a bool

Minimal Configuration

Smallest valid configuration:

_version = "1"

All other fields use defaults:

  • allowed_kinds = [] (all kinds allowed)
  • digits = 3
  • allow_unrecognised = false
  • allow_invalid = false
  • subfolders_are_namespaces = false

Default Configuration

If config.toml is absent, equivalent to:

_version = "1"
allowed_kinds = []
digits = 3
allow_unrecognised = false
allow_invalid = false
subfolders_are_namespaces = false

Configuration Examples

Small Project

_version = "1"
digits = 3
allow_unrecognised = false
allow_invalid = false

Large Project

_version = "1"
allowed_kinds = ["USR", "SYS", "SWR", "HWR", "TST", "DOC"]
digits = 4  # Expect 1000+ requirements per kind
allow_unrecognised = false
allow_invalid = false

Integrated Documentation

_version = "1"
allowed_kinds = ["USR", "SYS"]
digits = 3
allow_unrecognised = true  # Allow MdBook/Sphinx files
allow_invalid = false

Migration Project

_version = "1"
digits = 3
allow_unrecognised = true   # Mixed content during migration
allow_invalid = true         # Some requirements may be incomplete

Aerospace (DO-178C)

_version = "1"
allowed_kinds = ["URQT", "SRQT", "SWRQT", "HWRQT", "TRQT"]
digits = 4
allow_unrecognised = false
allow_invalid = false

Multi-Component System

_version = "1"
allowed_kinds = [
    "CORE-USR", "CORE-SYS",
    "AUTH-USR", "AUTH-SYS",
    "PAYMENT-USR", "PAYMENT-SYS",
    "REPORTING-USR", "REPORTING-SYS"
]
digits = 3
allow_unrecognised = false
allow_invalid = false

Validation

Parsing Errors

Missing _version:

allowed_kinds = ["USR"]
Error: Failed to parse config file: missing field '_version'

Invalid TOML syntax:

_version = "1
allowed_kinds = ["USR"]
Error: Failed to parse config file: expected '"', got newline

Wrong type:

_version = 1  # Should be string
Error: Failed to parse config file: invalid type: integer, expected a string

Unknown field (future-proofing):

_version = "1"
unknown_field = "value"

Currently allowed (forward compatibility), but may be rejected in strict mode.

Runtime Validation

Configuration is loaded at:

  • req add
  • req link
  • req clean

Errors reported immediately:

req clean
# Error: Failed to load config: missing field '_version'

Schema Evolution

Version 1 (Current)

Fields:

  • _version (required)
  • allowed_kinds (optional)
  • digits (optional)
  • allow_unrecognised (optional)
  • allow_invalid (optional)
  • subfolders_are_namespaces (optional)

Future Versions

Planned fields (not yet implemented):

Version 2 (hypothetical):

_version = "2"

# Existing fields
allowed_kinds = ["USR", "SYS"]
digits = 3
allow_unrecognised = false
allow_invalid = false

# New fields
[namespaces]
required = true
allowed = ["AUTH", "PAYMENT"]

[review]
auto_flag = true
notify = "team@example.com"

[coverage]
minimum = 95

Compatibility:

  • Old Requiem: Rejects _version = "2" (unknown version)
  • New Requiem: Reads _version = "1" (backward compatible)

Troubleshooting

Config Not Recognized

Problem: Changes to config.toml don't take effect.

Solution:

  • Ensure file is named exactly config.toml (lowercase, no extension)
  • Ensure file is in requirements root directory
  • Verify TOML syntax with validator

Parse Errors

Problem: Error: Failed to parse config file

Diagnosis:

  1. Check TOML syntax
  2. Ensure strings are quoted
  3. Ensure arrays use square brackets
  4. Check for typos in field names

Solution: Validate TOML:

# Python
python -c "import sys, toml; toml.load(open('config.toml'))"

# Online validator
# Copy config to https://www.toml-lint.com/

Requirements Rejected

Problem: req add fails with "Kind not in allowed list"

Diagnosis: Check allowed_kinds in config.

Solution: Add kind to allowed_kinds or use empty array:

allowed_kinds = []  # Allow all kinds

Files Ignored Unexpectedly

Problem: Valid requirement files not loaded.

Diagnosis: Check filename matches HRID pattern.

Solution:

  • Ensure filename is {KIND}-{ID}.md
  • Set allow_unrecognised = false to get error messages

Summary

Configuration file:

  • Location: config.toml in requirements root
  • Format: TOML
  • Optional: Uses defaults if absent

Required fields:

  • _version: Schema version (currently "1")

Optional fields:

  • allowed_kinds: Restrict requirement kinds (default: [], allow all)
  • digits: HRID digit padding (default: 3)
  • allow_unrecognised: Allow non-HRID files (default: false)
  • allow_invalid: Allow invalid requirements (default: false)
  • subfolders_are_namespaces: Use path-based structure (default: false)

Defaults:

  • All kinds allowed
  • 3-digit HRID padding
  • Strict file validation
  • Strict requirement validation
  • Filename-based directory structure

Next Steps