aboutsummaryrefslogtreecommitdiff
path: root/scripts/check-trace.sh
blob: bc026d47f305eb551f3381bd0eb82708cae1b2b5 (plain) (blame)
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
#!/usr/bin/env bash
#
# Bidirectional traceability check (docs/process.md §5).
#
# Verifies HLR -> LLR -> source -> test in both directions:
#   - every low-level requirement is implemented and tested
#   - every requirement a test names actually exists
#
# The third check is the one that is easy to omit and that fails silently when
# omitted: it catches stale references left behind by a renumbered or withdrawn
# requirement.
#
# Exits non-zero if any check fails, so it can gate a commit or CI job.

set -euo pipefail

cd "$(dirname "$0")/.."

tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT

grep -ohE  'MJB-LLR-[0-9]+' docs/requirements/llr.md | sort -u > "$tmp/defined"
grep -rohE 'MJB-LLR-[0-9]+' src/                     | sort -u > "$tmp/tagged"
grep -rohE 'mjb_llr_[0-9]+' src/ tests/ \
  | sed 's/mjb_llr_/MJB-LLR-/' | sort -u > "$tmp/tested"

defined=$(wc -l < "$tmp/defined")
tagged=$(wc -l  < "$tmp/tagged")
tested=$(wc -l  < "$tmp/tested")

printf 'defined=%s tagged=%s tested=%s\n\n' "$defined" "$tagged" "$tested"

status=0

report() { # $1=label  $2=file  $3=explanation
  if [ -s "$2" ]; then
    printf '%s:\n' "$1"
    sed 's/^/  /' "$2"
    printf '  -> %s\n\n' "$3"
    status=1
  fi
}

comm -23 "$tmp/defined" "$tmp/tagged"  > "$tmp/untagged"
comm -23 "$tmp/defined" "$tmp/tested"  > "$tmp/untested"
comm -13 "$tmp/defined" "$tmp/tested"  > "$tmp/unknown"

report "Requirements with no implementation" "$tmp/untagged" \
  "tag the implementing item with // MJB-LLR-nnn"
report "Requirements with no test" "$tmp/untested" \
  "add a test named mjb_llr_nnn_<description>"
report "Tests naming a requirement that does not exist" "$tmp/unknown" \
  "typo, or a stale reference to a withdrawn requirement"

if [ "$status" -eq 0 ]; then
  echo "OK: traceability complete in both directions."
fi

exit "$status"