montana/Монтана-Протокол/Код/scripts/pre-commit.sh

97 lines
4.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# spec, разделы [C-7] No-shortcut на apply_*, [C-8] Mandatory SC trace block,
# [C-10] Mandatory deviation tracker
#
# Установка: создать симлинк из этого файла в .git/hooks/pre-commit:
# ln -sf "$(pwd)/scripts/pre-commit.sh" .git/hooks/pre-commit
# (либо запустить scripts/install-hooks.sh)
#
# Этот hook применяется ТОЛЬКО на коммиты в crates/, не на role/spec правки.
set -e
REPO_ROOT="$(git rev-parse --show-toplevel)"
cd "$REPO_ROOT"
CHANGED=$(git diff --cached --name-only --diff-filter=ACM)
CONSENSUS_CHANGED=$(echo "$CHANGED" | grep -E 'crates/(mt-(state|account|entry|consensus|lottery|timechain)|montana-node)/.*\.rs$' || true)
# Gate 1 [C-8] SC trace block — проверяется в commit-msg hook (он получает
# commit message file как $1; pre-commit запускается ДО записи message
# и не имеет доступа к нему). См. scripts/commit-msg.sh.
# Gate 2 [C-10]: SPEC DEVIATION в коде требует DEV-N reference
BAD_DEV=$(git diff --cached -- 'crates/**/*.rs' 2>/dev/null | grep "^+.*SPEC DEVIATION" | grep -v "DEV-[0-9]" || true)
if [ -n "$BAD_DEV" ]; then
echo "ОТКАЗ [C-10]: SPEC DEVIATION без DEV-N reference"
echo "$BAD_DEV"
echo
echo "Каждое // SPEC DEVIATION: ОБЯЗАНО ссылаться на конкретный DEV-NNN entry в docs/SPEC_DEVIATIONS.md"
exit 1
fi
# Gate 3 [C-10]: deviation count в коде vs SPEC_DEVIATIONS.md
if [ -f docs/SPEC_DEVIATIONS.md ]; then
CODE_DEVS=$(grep -rcE "SPEC DEVIATION DEV-[0-9]+" crates/ 2>/dev/null | grep -v ":0$" | awk -F: '{s+=$2} END {print s+0}')
DOC_DEVS=$(grep -c "^## DEV-" docs/SPEC_DEVIATIONS.md 2>/dev/null || echo 0)
if [ "$CODE_DEVS" -gt "$DOC_DEVS" ]; then
echo "ОТКАЗ [C-10]: $CODE_DEVS SPEC DEVIATION в коде, $DOC_DEVS entries в docs/SPEC_DEVIATIONS.md"
echo "Каждый DEV-NNN в коде должен иметь entry в SPEC_DEVIATIONS.md"
exit 1
fi
fi
# Gate 4 [C-7]: запрет прямого mut на consensus state в node/example crates.
# Контекст ±3 строки: cargo fmt может переместить `// SPEC DEVIATION DEV-N`
# comment на отдельную строку (struct literal multi-line) — hook должен видеть
# deviation marker в окрестности, не только на той же строке.
# Gate 4 scope: production binary code только. cargo example bins
# (crates/*/examples/*.rs) — shakedown demos, не consensus path.
BAD_MUT=$(git diff --cached -U3 -- 'crates/montana-node/**/*.rs' ':!crates/*/examples/*.rs' 2>/dev/null \
| awk '
/^\+/ && /\.(insert|remove)\(/ && /(accounts|nodes|candidates|account_table|node_table|candidate_pool)/ {
lines[NR] = $0
target_line[NR] = 1
}
/SPEC DEVIATION DEV-/ {
dev_line[NR] = 1
}
END {
for (n in target_line) {
has_dev = 0
for (k = n - 3; k <= n + 3; k++) {
if (dev_line[k]) { has_dev = 1; break }
}
if (!has_dev) print lines[n]
}
}
' \
|| true)
if [ -n "$BAD_MUT" ]; then
echo "ОТКАЗ [C-7]: прямой mut-доступ к consensus state таблице вне apply_* функции"
echo "$BAD_MUT"
echo
echo "Прямой insert/remove на AccountTable/NodeTable/CandidatePool разрешён только внутри apply_* функций соответствующего crate"
echo "Если deviation legitimate — добавьте // SPEC DEVIATION DEV-NNN с обоснованием в docs/SPEC_DEVIATIONS.md в пределах ±3 строк от insert/remove"
exit 1
fi
# Gate 5: четыре обязательные команды (workspace level)
# Этот gate тяжёлый — запускается только если consensus-critical изменены
if [ -n "$CONSENSUS_CHANGED" ]; then
echo "Pre-commit: проверка fmt..."
cargo fmt --all -- --check >/dev/null 2>&1 || {
echo "ОТКАЗ: cargo fmt --all -- --check не прошёл"
cargo fmt --all -- --check
exit 1
}
echo "Pre-commit: проверка clippy..."
cargo clippy --all-targets -- -D warnings >/dev/null 2>&1 || {
echo "ОТКАЗ: cargo clippy не прошёл"
cargo clippy --all-targets -- -D warnings 2>&1 | tail -30
exit 1
}
fi
echo "Pre-commit: все проверки пройдены"