#!/bin/sh # # Requirement traceability gate. Run locally exactly as CI runs it: # # scripts/traceability/traceability-gate.sh # # Writes traces-report.json and docs/traceability.md, prints the coverage # report, and exits non-zero when the gate fails. # # Environment: # MIN_COVERAGE minimum overall coverage percent (default 0 - see below) # ALLOW_ORPHANS set to 1 to report orphan tags without failing # TRACES_JSON JSON report path (default traces-report.json) # TRACES_MD markdown matrix path (default docs/traceability.md) # SYSTEM_SPEC optional path to the umbrella SPEC.md, which defines the # PR/SR IDs; when given, PR/SR orphans are reported too. That # file lives in the parent project, not in this repo, so CI # normally leaves it unset. # # Threshold policy lives here and nowhere else. It is deliberately NOT # duplicated into the workflow YAML: a threshold written in two places is a # threshold that will disagree with itself. # # MIN_COVERAGE defaults to 0 because almost nothing is tagged yet - tags are # added as the pipeline is built, so a low number today is accurate rather than # alarming. A zero threshold does NOT mean the gate cannot fail: orphan tags, # a >100% ratio, a register that parses to nothing, and an empty source scan # are all hard failures from day one. Raise MIN_COVERAGE as tags land; treat # every raise as a ratchet, never a reset. # # POSIX sh, no bashisms, no jq - the extractor does its own arithmetic and # printing so CI needs nothing beyond python3. set -eu SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR/../.." && pwd) MIN_COVERAGE="${MIN_COVERAGE:-0}" TRACES_JSON="${TRACES_JSON:-$REPO_ROOT/traces-report.json}" TRACES_MD="${TRACES_MD:-$REPO_ROOT/docs/traceability.md}" PYTHON="${PYTHON:-python3}" command -v "$PYTHON" >/dev/null 2>&1 || { echo "FAILED: $PYTHON not found. The traceability gate needs Python 3.9+" >&2 exit 2 } set -- \ --root "$REPO_ROOT" \ --format coverage \ --json-out "$TRACES_JSON" \ --markdown-out "$TRACES_MD" \ --min-coverage "$MIN_COVERAGE" if [ "${ALLOW_ORPHANS:-0}" = "1" ]; then set -- "$@" --allow-orphans fi if [ -n "${SYSTEM_SPEC:-}" ]; then set -- "$@" --system-spec "$SYSTEM_SPEC" fi exec "$PYTHON" "$SCRIPT_DIR/extract_traces.py" "$@"