79 lines
2.5 KiB
Bash
Executable File
79 lines
2.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# validate-audit-report.sh
|
|
# Structural + semantic validation for CODEX audit reports.
|
|
set -euo pipefail
|
|
|
|
REPORT_PATH="${1:-CODEX-REPORT.md}"
|
|
|
|
if [[ ! -f "$REPORT_PATH" ]]; then
|
|
echo "[validate-audit-report] Missing report: $REPORT_PATH"
|
|
exit 1
|
|
fi
|
|
|
|
FAILURES=0
|
|
|
|
# --- Check 1: Required sections exist ---
|
|
required_sections=(
|
|
"## Requirements Mapping"
|
|
"## Constitution Compliance Matrix"
|
|
"## Evidence"
|
|
"## Risks"
|
|
)
|
|
|
|
for section in "${required_sections[@]}"; do
|
|
if command -v rg >/dev/null 2>&1; then
|
|
if ! rg -q "^${section//\//\\/}$" "$REPORT_PATH"; then
|
|
echo "[validate-audit-report] Missing section: $section"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
else
|
|
if ! grep -Eq "^${section//\//\\/}$" "$REPORT_PATH"; then
|
|
echo "[validate-audit-report] Missing section: $section"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# --- Check 2: Reject forbidden placeholders ---
|
|
forbidden_patterns=("TODO" "TBD" "UNMAPPED" "PLACEHOLDER" "FIXME")
|
|
for pattern in "${forbidden_patterns[@]}"; do
|
|
if command -v rg >/dev/null 2>&1; then
|
|
count="$(rg -c "$pattern" "$REPORT_PATH" 2>/dev/null || echo 0)"
|
|
else
|
|
count="$(grep -c "$pattern" "$REPORT_PATH" 2>/dev/null || echo 0)"
|
|
fi
|
|
if [[ "$count" -gt 0 ]]; then
|
|
echo "[validate-audit-report] Forbidden placeholder '$pattern' found ($count occurrences)"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
done
|
|
|
|
# --- Check 3: Non-empty sections (at least 1 non-blank line after heading) ---
|
|
for section in "${required_sections[@]}"; do
|
|
# Extract content between this heading and the next ## heading (or EOF)
|
|
section_escaped="${section//\//\\/}"
|
|
content=""
|
|
if command -v awk >/dev/null 2>&1; then
|
|
content="$(awk "/^${section_escaped}\$/{found=1; next} found && /^## /{exit} found{print}" "$REPORT_PATH" | grep -v '^[[:space:]]*$' || true)"
|
|
fi
|
|
if [[ -z "$content" ]]; then
|
|
echo "[validate-audit-report] Section is empty: $section"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
done
|
|
|
|
# --- Check 4: Requirements mapping has entries (table rows or list items) ---
|
|
req_entries="$(awk '/^## Requirements Mapping$/{found=1; next} found && /^## /{exit} found && /^\|[^-]/{print} found && /^- /{print}' "$REPORT_PATH" | wc -l | tr -d ' ')"
|
|
if [[ "$req_entries" -lt 1 ]]; then
|
|
echo "[validate-audit-report] Requirements Mapping has no entries (expected table rows or list items)"
|
|
FAILURES=$((FAILURES + 1))
|
|
fi
|
|
|
|
# --- Result ---
|
|
if [[ $FAILURES -gt 0 ]]; then
|
|
echo "[validate-audit-report] FAILED ($FAILURES issues)"
|
|
exit 1
|
|
fi
|
|
|
|
echo "[validate-audit-report] PASS ($REPORT_PATH)"
|