#!/usr/bin/env bash # scripts/gate-report 的迴歸測試(inkstone/InkStoneCo#48 驗收 #2) # # 用一份寫死的 fixture 帳本,驗這三題「查得出來、答得對」,不是憑印象: # Q1 哪支閘擋最多?其中多少被繞過? # Q2 哪條規則最近 N 天一次都沒擋過? # Q3 同一個 session 反覆撞同一支閘幾次? # 🔴 出路要真的走得通(mistakes.md #158):這裡不驗「有沒有印字」, # 驗「印出來的數字對不對」。 set -u REPORT="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/gate-report}" TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT LED="$TMP/gate-log.jsonl" PASS=0; FAIL=0; N=0 ok() { N=$((N+1)); printf ' ✅ %s\n' "$1"; PASS=$((PASS+1)); } bad() { N=$((N+1)); printf ' ❌ %s\n' "$1"; FAIL=$((FAIL+1)); shift; for l in "$@"; do printf ' %s\n' "$l"; done; } NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ) OLD=$(python3 -c "import datetime as d;print((d.datetime.now(d.timezone.utc)-d.timedelta(days=30)).strftime('%Y-%m-%dT%H:%M:%SZ'))") row() { printf '{"ts":"%s","gate":"%s","event":"PreToolUse","tool":"Bash","verdict":"%s","bypass":"%s","sid":"%s","child":%s}\n' \ "$1" "$2" "$3" "$4" "$5" "${6:-0}" >> "$LED"; } # gateA:擋 3 次、繞過 2 次(誤擋嫌疑最高);session sA 撞它 3 次 row "$NOW" gateA block "" sA 0 row "$NOW" gateA block "" sA 0 row "$NOW" gateA block "" sA 0 # sA 撞 gateA 共 3 次(Q3) row "$NOW" gateA bypass NOT_MY_BRANCH_OK sB 1 row "$NOW" gateA bypass NOT_MY_BRANCH_OK sB 1 # gateB:擋 1 次 row "$NOW" gateB block "" sC 0 # gateC:最近只有放行,從沒擋過(Q2 該點名) row "$NOW" gateC pass "" sC 0 row "$NOW" gateC pass "" sD 0 # gateD:只有 30 天前擋過,最近 7 天沒擋(Q2 該點名) row "$OLD" gateD block "" sE 0 echo "── Q1:擋最多的是 gateA,且看得出被繞過 2 次 ────────────────" Q1=$(ISEP_GATE_LOG="$LED" "$REPORT" q1 2>&1) FIRST=$(printf '%s' "$Q1" | grep -E '^\s+gate[A-Z]' | head -n1) case "$FIRST" in *gateA*) ok "① 誤擋嫌疑排序第一名是 gateA" ;; *) bad "① 排序第一名不是 gateA" "$Q1" ;; esac # gateA 那行:擋下 3、被繞過 2、本要擋 5 if printf '%s' "$Q1" | grep -E 'gateA' | grep -qE '\b3\b.*\b2\b.*\b5\b'; then ok "② gateA 的數字對:擋下3 / 被繞過2 / 本要擋5" else bad "② gateA 數字不對" "$(printf '%s' "$Q1" | grep gateA)"; fi echo "── Q2:最近 7 天沒擋過的是 gateC(只放行)與 gateD(30天前才擋)─" Q2=$(ISEP_GATE_LOG="$LED" "$REPORT" q2 --days 7 2>&1) printf '%s' "$Q2" | grep -q 'gateC' && ok "③ gateC(活著但只放行)被點名" || bad "③ 沒點名 gateC" "$Q2" printf '%s' "$Q2" | grep -q 'gateD' && ok "④ gateD(最近7天沒擋)被點名" || bad "④ 沒點名 gateD" "$Q2" printf '%s' "$Q2" | grep -qE '^\s+·\s+gateA' && bad "⑤ 誤點名 gateA(它最近有擋)" "$Q2" || ok "⑤ 有擋過的 gateA 不被點名" echo "── Q3:sA 反覆撞 gateA 3 次 ─────────────────────────────────" Q3=$(ISEP_GATE_LOG="$LED" "$REPORT" q3 2>&1) if printf '%s' "$Q3" | grep -E 'gateA' | grep -q 'sA'; then if printf '%s' "$Q3" | grep -E 'sA' | grep -qE '\b3\b'; then ok "⑥ sA 撞 gateA 記成 3 次"; else bad "⑥ 次數不是 3" "$Q3"; fi else bad "⑥ 沒抓到 sA×gateA" "$Q3"; fi # sC 撞 gateB 只 1 次,不該出現在 Q3 printf '%s' "$Q3" | grep -E 'gateB' | grep -q 'sC' && bad "⑦ 撞1次的 sC×gateB 不該出現" "$Q3" || ok "⑦ 只撞1次的不入 Q3" echo "── 基線:空帳本也要能跑(不爆炸)───────────────────────────" EMPTY="$TMP/empty.jsonl"; : > "$EMPTY" if ISEP_GATE_LOG="$EMPTY" "$REPORT" all >/dev/null 2>&1; then ok "⑧ 空帳本跑 all 不報錯"; else bad "⑧ 空帳本跑 all 爆了"; fi echo "" echo "通過 $PASS 條,失敗 $FAIL 條(共 $N)" [ "$FAIL" = 0 ]