feat(lib): floor-guard, diff-scoped detector of a weakened quality bar

SUPPRESS / SKIP / DELETED_TEST / ASSERT_DROP / STUB / THRESHOLD_DOWN over
git diff <base> (untracked files included), floor-guard: allow <reason>
waiver printed as WAIVED, rc 0/2/3. Mandatory verifier STEP 3, documented
under GATE 1 of verify-secure-loop.md. Suite: 6 kinds + WAIVED + CLEAN,
flip-tested. Adapted from agent-skills constraint-driven-development.
This commit is contained in:
bastien
2026-09-27 20:17:36 +02:00
parent d28c45ed19
commit 2b25cb4704
4 changed files with 439 additions and 10 deletions
+95
View File
@@ -0,0 +1,95 @@
#!/usr/bin/env bash
# lib/tests/floor-guard.test.sh — flip-tests for lib/floor-guard.sh: one RED
# fixture per KIND, one WAIVED fixture, one CLEAN fixture. Each fixture is a
# fresh throwaway repo under $WORK (`make test` exports
# GIT_CONFIG_GLOBAL=/dev/null; core.hooksPath is also pinned per-repo so a
# machine-wide hook never fires here). This file itself carries the trigger
# strings for every kind — the self-run criterion excludes it by pathspec.
set -u
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
LIB="$ROOT/lib/floor-guard.sh"
WORK="$(mktemp -d)"; trap 'rm -rf "$WORK"' EXIT
pass=0; fail=0
# check_kind <KIND> <rc> <want_rc> <out> <want_substr>
check_kind() {
local kind="$1" rc="$2" want_rc="$3" out="$4" want_sub="$5"
if [ "$rc" = "$want_rc" ] && printf '%s\n' "$out" | grep -qF -- "$want_sub"; then
pass=$((pass+1)); echo "PASS $kind"
else
fail=$((fail+1))
printf 'FAIL %s: rc=%s (want %s), out:\n%s\n' \
"$kind" "$rc" "$want_rc" "$(printf '%s\n' "$out" | tail -5)"
fi
}
# mk_repo <name> → path to a fresh throwaway repo: one test file (3
# assertions), one vitest.config.ts (coverage.lines: 80), one source file.
mk_repo() {
local d="$WORK/$1"
mkdir -p "$d/src"
git init -q "$d"
git -C "$d" config user.email t@t
git -C "$d" config user.name t
git -C "$d" config core.hooksPath /dev/null
printf 'expect(1).toBe(1);\nexpect(2).toBe(2);\nexpect(3).toBe(3);\n' \
> "$d/sample.test.js"
printf 'export default {\n coverage: {\n lines: 80,\n },\n};\n' \
> "$d/vitest.config.ts"
printf 'function add(a, b) {\n return a + b;\n}\n' > "$d/src/index.js"
git -C "$d" add -A
git -C "$d" commit -q -m base
echo "$d"
}
# ── SUPPRESS ──────────────────────────────────────────────────────────────
d=$(mk_repo suppress); base=$(git -C "$d" rev-parse HEAD)
echo '// eslint-disable-next-line no-console' >> "$d/src/index.js"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind SUPPRESS "$rc" 2 "$out" 'FLOOR SUPPRESS'
# ── SKIP ──────────────────────────────────────────────────────────────────
d=$(mk_repo skip); base=$(git -C "$d" rev-parse HEAD)
echo "it.skip('later', () => {});" >> "$d/sample.test.js"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind SKIP "$rc" 2 "$out" 'FLOOR SKIP'
# ── DELETED_TEST ──────────────────────────────────────────────────────────
d=$(mk_repo deleted); base=$(git -C "$d" rev-parse HEAD)
rm "$d/sample.test.js"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind DELETED_TEST "$rc" 2 "$out" 'FLOOR DELETED_TEST'
# ── ASSERT_DROP ───────────────────────────────────────────────────────────
d=$(mk_repo assertdrop); base=$(git -C "$d" rev-parse HEAD)
printf 'expect(1).toBe(1);\n' > "$d/sample.test.js"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind ASSERT_DROP "$rc" 2 "$out" 'FLOOR ASSERT_DROP'
# ── STUB ──────────────────────────────────────────────────────────────────
d=$(mk_repo stub); base=$(git -C "$d" rev-parse HEAD)
echo "function todo() { throw new Error('not implemented'); }" >> "$d/src/index.js"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind STUB "$rc" 2 "$out" 'FLOOR STUB'
# ── THRESHOLD_DOWN ────────────────────────────────────────────────────────
d=$(mk_repo threshold); base=$(git -C "$d" rev-parse HEAD)
sed -i 's/lines: 80/lines: 60/' "$d/vitest.config.ts"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind THRESHOLD_DOWN "$rc" 2 "$out" 'FLOOR THRESHOLD_DOWN'
# ── WAIVED ────────────────────────────────────────────────────────────────
d=$(mk_repo waived); base=$(git -C "$d" rev-parse HEAD)
echo '// eslint-disable-next-line no-console -- floor-guard: allow legacy shim' \
>> "$d/src/index.js"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind WAIVED "$rc" 0 "$out" 'WAIVED'
# ── CLEAN ─────────────────────────────────────────────────────────────────
d=$(mk_repo clean); base=$(git -C "$d" rev-parse HEAD)
echo '// helper' >> "$d/src/index.js"
out=$(cd "$d" && bash "$LIB" "$base" 2>&1); rc=$?
check_kind CLEAN "$rc" 0 "$out" 'FLOOR GUARD: clean'
echo "PASS=$pass FAIL=$fail"
[ "$fail" -eq 0 ]