requirements-manager 0.1.1

Plain-text requirements management tool
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
# 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:

```yaml
# 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:

```bash
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**:
```bash
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**:
```markdown
---
_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:
```yaml
# SYS-001.md links to USR-001
parents:
- uuid: 4bfeb7d5-...
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
  hrid: USR-001
```

2. Someone edits `USR-001`:
```markdown
# USR-001.md
The system shall validate user email addresses according to RFC 5322.
Email validation must occur before account creation.  # ← New sentence
```

3. USR-001's fingerprint changes:
```
New fingerprint: c4020419ead000e9b5f9cfd4ebf6192e73f905c27e6897548d8f6e12fd7f1356
```

4. SYS-001 still has the old fingerprint:
```yaml
# SYS-001.md
parents:
- fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda  # Old!
```

5. **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**:

```bash
# 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):

```bash
# 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**

```bash
# 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:

```bash
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:
```yaml
# SYS-001.md
parents:
- uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a
  fingerprint: e533784ff58c16cbf08e436cb06f09e0076880fd707baaf55aa0f45dc4a6ccda
```

2. Compute current fingerprint of parent (see above)

3. Compare:
   - Match: Child is current
   - Mismatch: Child needs review

## What Changes Affect Fingerprints

### Changes that Update Fingerprints

**Editing requirement text**:
```markdown
# Before
The system shall validate emails.

# After
The system shall validate emails according to RFC 5322.
```
→ Fingerprint changes

**Adding/removing tags**:
```yaml
# Before
tags:
- authentication

# After
tags:
- authentication
- security
```
→ Fingerprint changes

**Modifying tags**:
```yaml
# Before
tags:
- high-priority

# After
tags:
- medium-priority
```
→ Fingerprint changes

**Whitespace changes in content**:
```markdown
# 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**:
```bash
mv USR-001.md USR-100.md
```
→ Fingerprint unchanged (HRID is not part of content)

**Changing UUID** (don't do this!):
```yaml
# Before
uuid: 4bfeb7d5-d168-44a7-b0f1-e292c1c89b9a

# After
uuid: 00000000-0000-0000-0000-000000000000
```
→ Fingerprint unchanged (but breaks traceability!)

**Changing created timestamp**:
```yaml
# Before
created: 2025-07-22T12:19:56Z

# After
created: 2025-08-01T10:00:00Z
```
→ Fingerprint unchanged

**Adding/removing parents**:
```yaml
# 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**:

```bash
# 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**:
```bash
# 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**:
```yaml
# USR-001.md
tags:
- authentication
```

Fingerprint: `e533784f...`

**After**:
```yaml
# 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**:
```markdown
The system shall validate emails.
```

**After**:
```markdown
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:
```bash
req suspect
# Lists all requirements with fingerprint mismatches
```

**✓ Accepting suspect links**

Update fingerprints after review:
```bash
# Accept individual link
req accept SYS-001 USR-001

# Accept all suspect links
req accept --all
```

**✓ CI/CD integration**

Exit codes enable automation:
```bash
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**:
```bash
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**:
```bash
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**:
```bash
req report review
# Generate review status report with metrics
```

## Best Practices

### 1. Link Immediately After Creation

When creating a requirement with parents:

```bash
# Create requirement
req add SYS --parents USR-001

# Fingerprint is captured immediately
```

This ensures the fingerprint represents the baseline.

### 2. Check for Suspect Links Regularly

Periodically check for fingerprint mismatches:

```bash
# Check for suspect links
req suspect

# Before committing changes
req suspect || (echo "Review needed" && exit 1)

# In CI/CD pipeline
req suspect
```

### 3. Accept Links After Review

After reviewing parent changes and updating children:

```bash
# 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:

```markdown
## 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**:
```bash
# 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:
```bash
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

- Learn about [Review Workflows]./review-workflows.md (planned feature)
- Understand [Correcting HRIDs]./correcting-hrids.md for maintaining references