PureXML/scripts/check-style.sh
Mihaela Mihaljevic c7ef8abfd9 chore(rules): pin rules-swift corpus, add gates and CI; drop redundant docs/rules mirror
Adopt the rules-swift pin-and-codify strategy in snapshot mode (third_party/rules-swift
@97dc70f + sha256), add codified gates, a conformance audit ledger, and
.github/workflows/rules-swift.yml (corpus-pin integrity required, full gate report mode).
Remove the docs/rules mirror it supersedes (repo-specific files kept under docs/). Style
and leak gates exclude the vendored corpus.
2026-06-30 14:02:40 +02:00

76 lines
2.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Repo-wide style gate: no em dashes, no tool-attribution phrases in any tracked
# file. Mirrors the .githooks checks, run over the whole tree in CI so a bypassed
# local hook is still caught at merge time.
#
# Portable: BSD-compatible grep, bash 3.2 (macOS) and bash 4+ (CI).
set -u
FAIL=0
# Em dash U+2014, built via printf so this script contains no em-dash byte.
EMDASH=$(printf '\xe2\x80\x94')
# Enforcement files legitimately contain the forbidden phrases in order to
# detect them, so exclude them from the phrase scan.
is_enforcement_file() {
case "$1" in
.githooks/*|scripts/check-style.sh|scripts/check-commit-attribution.sh|third_party/rules-swift/core/commits.md|third_party/rules-swift/core/git-discipline.md) return 0 ;;
*) return 1 ;;
esac
}
# Tool-attribution phrases. Assembled from fragments so this script does not
# contain the full literal phrases (which would self-flag in other scanners).
TOOL="Cla""ude"
PHRASES=(
"Co-Authored-By: $TOOL"
"Co-authored-by: $TOOL"
"Generated with $TOOL"
"Generated by $TOOL"
"Powered by $TOOL"
"as an AI"
)
# Vendor-neutral attribution: Rule 5.1 covers every AI assistant. Vendor names in
# a list, matched against attribution prefixes, so the gate is tool-agnostic.
AI_VENDORS="Codex Copilot Gemini ChatGPT OpenAI Anthropic Cursor"
AI_PREFIXES='Co-Authored-By:|Co-authored-by:|Generated with|Generated by|with help from|Powered by'
while IFS= read -r f; do
[ -f "$f" ] || continue
# The vendored rules-swift corpus is pinned upstream content, not authored here.
case "$f" in third_party/*) continue ;; esac
if LC_ALL=C grep -qF -- "$EMDASH" "$f" 2>/dev/null; then
echo "style: em dash (U+2014) in $f" >&2
FAIL=1
fi
if ! is_enforcement_file "$f"; then
for p in "${PHRASES[@]}"; do
if LC_ALL=C grep -qF -- "$p" "$f" 2>/dev/null; then
echo "style: forbidden attribution phrase in $f" >&2
FAIL=1
fi
done
# Vendor-neutral attribution (Rule 5.1 covers every assistant, not just Claude).
for vendor in $AI_VENDORS; do
if LC_ALL=C grep -qiE -- "($AI_PREFIXES) $vendor" "$f" 2>/dev/null; then
echo "style: forbidden attribution phrase ($vendor) in $f" >&2
FAIL=1
fi
done
fi
done < <(git ls-files)
if [ "$FAIL" -ne 0 ]; then
echo "style: gate failed. Rules: third_party/rules-swift/core/git-discipline.md" >&2
fi
# Roadmap gate (github-discipline: the roadmap check is wired into check-style).
if ! bash scripts/check-roadmap.sh; then
FAIL=1
fi
exit "$FAIL"