test(plan-gates): gate-scriptene fra revisjonen 04.09, kjoerbare fra repoet
De to maskinelle sjekkene paa at planrevisjonen holder laa i en scratchpad og var i ferd med aa bli borte (samme naeromkomst som oekt 2s script). Flyttet inn i repoet, gjort sted-uavhengige (repo-roten resolveres fra $0) og med en guard naar plan.md/brief.md mangler -- de er local-only paa denne offentlige remoten, og «fant ingenting» skal ikke lese som «alt groent» (exit 2, ikke 0). Kjoert fra tests/plan-gates/ etter flyttingen: brief_criteria.sh PASS=33 FAIL=0 stale_text.sh PASS=12 FAIL=0 Negativkontroll: mot en tom plan gir brief_criteria.sh PASS=6 FAIL=27 og exit 1, og manglende fil gir SKIP + exit 2. Gaten kan altsaa feile. PM-autorisert forsteg (amendment til ordre 20260904T150903Z), utenfor planens sesjon-1-gjerde. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
2076f617e0
commit
2f99ac5951
2 changed files with 117 additions and 0 deletions
60
tests/plan-gates/brief_criteria.sh
Executable file
60
tests/plan-gates/brief_criteria.sh
Executable file
|
|
@ -0,0 +1,60 @@
|
|||
#!/bin/bash
|
||||
# The 33 gate criteria from brief.md "Success Criteria -> For the plan".
|
||||
# Written in session 2 of the planning work, moved into the repo 2026-09-04 so
|
||||
# the only machine check on the plan is not a scratchpad file. Runnable from
|
||||
# anywhere: the repo root is resolved from this script's own location.
|
||||
#
|
||||
# The plan it checks lives under .claude/projects/, which is gitignored on this
|
||||
# public remote (.gitignore:19). A fresh clone therefore has no plan to gate --
|
||||
# that is a missing measurement, not a pass, and exits 2.
|
||||
#
|
||||
# Usage: tests/plan-gates/brief_criteria.sh [path-to-plan.md]
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
ROOT=$(cd "$SCRIPT_DIR/../.." && pwd)
|
||||
PLAN="${1:-$ROOT/.claude/projects/2026-09-03-jobbsok-plugin-build/plan.md}"
|
||||
if [ ! -f "$PLAN" ]; then
|
||||
echo "SKIP plan not found: $PLAN"
|
||||
echo " (local-only artefact; nothing was measured -- this is not a pass)"
|
||||
exit 2
|
||||
fi
|
||||
pass=0; fail=0
|
||||
chk() { # chk "<name>" "<actual>" "<expected>"
|
||||
if [ "$2" = "$3" ]; then echo "PASS $1"; pass=$((pass+1));
|
||||
else echo "FAIL $1 (got '$2', want '$3')"; fail=$((fail+1)); fi
|
||||
}
|
||||
ge() { # ge "<name>" "<actual>" "<min>"
|
||||
if [ "$2" -ge "$3" ] 2>/dev/null; then echo "PASS $1 ($2 >= $3)"; pass=$((pass+1));
|
||||
else echo "FAIL $1 (got '$2', want >= $3)"; fail=$((fail+1)); fi
|
||||
}
|
||||
chk "milestone order" "$(grep -oE '^## .*\bM[1-6]\b' "$PLAN" | grep -oE 'M[1-6]' | tr -d '\n')" "M1M2M3M4M5M6"
|
||||
if grep -oE '^### Step [0-9]+: M[1-6]' "$PLAN" | grep -oE 'M[1-6]$' | sort -c 2>/dev/null; then
|
||||
echo "PASS step milestone tokens non-decreasing"; pass=$((pass+1))
|
||||
else echo "FAIL step milestone tokens not sorted"; fail=$((fail+1)); fi
|
||||
chk "all steps carry M token" "$(grep -c '^### Step [0-9]*: M[1-6]' "$PLAN")" "$(grep -c '^### Step ' "$PLAN")"
|
||||
ge "guard tag v1.3.0" "$(grep -c 'v1.3.0' "$PLAN")" 1
|
||||
chk "no vendoring" "$(grep -n 'vendor' "$PLAN" | grep -viE 'not vendored|never vendor|ikke vendor|do not vendor' | wc -l | tr -d ' ')" "0"
|
||||
chk "no gemini" "$(grep -n -i 'gemini' "$PLAN" | grep -viE 'no gemini|never|forbidden|excluded|ikke' | wc -l | tr -d ' ')" "0"
|
||||
chk "no commands dir" "$(grep -n 'commands/' "$PLAN" | grep -viE 'no commands|never|not create|ikke' | wc -l | tr -d ' ')" "0"
|
||||
chk "no imap" "$(grep -n -i 'imap' "$PLAN" | grep -viE 'no imap|deferred|not built|ikke|excluded|without imap|manual' | wc -l | tr -d ' ')" "0"
|
||||
for s in vurderer soker sendt dialog intervju tilbud avsluttet avslag trukket; do
|
||||
ge "transition names $s" "$(grep -cE "(test|transisjon|transition).*\b$s\b" "$PLAN")" 1
|
||||
done
|
||||
ge "14 days" "$(grep -cE '14 (days|dager)' "$PLAN")" 1
|
||||
ge "7 days" "$(grep -cE '\b7 (days|dager)' "$PLAN")" 1
|
||||
ge "10 days" "$(grep -cE '10 (days|dager)' "$PLAN")" 1
|
||||
ge "instruction override" "$(grep -ciE 'instruction override|instruksjonsoverstyring' "$PLAN")" 1
|
||||
ge "zero-click/exfil" "$(grep -ciE 'zero-click|exfil' "$PLAN")" 1
|
||||
ge "hidden unicode" "$(grep -ciE 'hidden unicode|skjult unicode' "$PLAN")" 1
|
||||
ge "FAIL_SECURE x3" "$(grep -c 'FAIL_SECURE' "$PLAN")" 3
|
||||
ge "QUARANTINE_REVIEW" "$(grep -c 'QUARANTINE_REVIEW' "$PLAN")" 1
|
||||
ge "Verifiser i Cowork x6" "$(grep -c 'Verifiser i Cowork' "$PLAN")" 6
|
||||
ge "playwright 0.0.80" "$(grep -c '0.0.80' "$PLAN")" 1
|
||||
ge "browser_run_code_unsafe" "$(grep -c 'browser_run_code_unsafe' "$PLAN")" 1
|
||||
ge "PreToolUse" "$(grep -ci 'pretooluse' "$PLAN")" 1
|
||||
ge "tools/list" "$(grep -c 'tools/list' "$PLAN")" 1
|
||||
ge "jobbsok-tools" "$(grep -c 'jobbsok-tools' "$PLAN")" 1
|
||||
ge "laering >=10 decisions" "$(grep -ciE '(>=|minst|at least) ?10 (decisions|beslutninger)' "$PLAN")" 1
|
||||
ge "hard filters" "$(grep -ciE 'hard filter|harde filtre' "$PLAN")" 1
|
||||
echo "----"
|
||||
echo "PASS=$pass FAIL=$fail"
|
||||
[ "$fail" -eq 0 ]
|
||||
57
tests/plan-gates/stale_text.sh
Executable file
57
tests/plan-gates/stale_text.sh
Executable file
|
|
@ -0,0 +1,57 @@
|
|||
#!/bin/bash
|
||||
# The twelve greps behind the "Foreldet tekst" table in
|
||||
# docs/2026-09-04-kvalitetsrevisjon-planlegging.md. Moved into the repo
|
||||
# 2026-09-04 (PM amendment) so the revision has a machine check that survives
|
||||
# the scratchpad. Runnable from anywhere: the repo root is resolved from this
|
||||
# script's own location.
|
||||
#
|
||||
# Scope: LIVE instruction text only. The `## Revisions` log and passages that
|
||||
# quote the brief's wording in order to disclaim it are the record of the fix,
|
||||
# not the defect; greps 1-4 exclude them by construction.
|
||||
#
|
||||
# plan.md and brief.md live under .claude/projects/, gitignored on this public
|
||||
# remote (.gitignore:19). A fresh clone has nothing to gate -- that is a missing
|
||||
# measurement, not a pass, and exits 2.
|
||||
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
ROOT=$(cd "$SCRIPT_DIR/../.." && pwd)
|
||||
D="$ROOT/.claude/projects/2026-09-03-jobbsok-plugin-build"
|
||||
P="$D/plan.md"
|
||||
B="$D/brief.md"
|
||||
for f in "$P" "$B"; do
|
||||
if [ ! -f "$f" ]; then
|
||||
echo "SKIP not found: $f"
|
||||
echo " (local-only artefact; nothing was measured -- this is not a pass)"
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
LIVE=$(mktemp -t jobbsok-plan-live) || exit 2
|
||||
trap 'rm -f "$LIVE"' EXIT
|
||||
sed -n '1,/^## Revisions/p' "$P" | sed '$d' > "$LIVE"
|
||||
pass=0; fail=0
|
||||
chk() { if [ "$2" = "$3" ]; then echo "PASS $1 ($2)"; pass=$((pass+1));
|
||||
else echo "FAIL $1 (got '$2', want '$3')"; fail=$((fail+1)); fi; }
|
||||
|
||||
# 1-2 blocker 9: no zip -r survives as an instruction in either file
|
||||
chk "1 plan zip -r as instruction" "$(grep -n 'zip -r' "$LIVE" | grep -viE '\*\*not\*\*|is not |never|instead' | wc -l | tr -d ' ')" "0"
|
||||
chk "2 brief zip -r as instruction" "$(grep -n 'zip -r' "$B" | grep -viE '\*\*not\*\*|is not |Not `zip|never|instead' | wc -l | tr -d ' ')" "0"
|
||||
# 3-4 finding 2: "the version-echo skill" survives only as a quoted deviation
|
||||
chk "3 brief version-echo skill" "$(grep -ci 'the version-echo skill' "$B" | tr -d ' ')" "0"
|
||||
chk "4 plan version-echo unquoted" "$(grep -n 'the version-echo skill' "$LIVE" | grep -vc 'phrase "the version-echo skill"' | tr -d ' ')" "0"
|
||||
# 5 blocker 15: step 20's unqualified reader claim is gone
|
||||
chk "5 writes nothing: reader" "$(grep -c 'The script writes nothing: it is a reader' "$P" | tr -d ' ')" "0"
|
||||
# 6 finding 2: step 23 carries the dagens version echo
|
||||
chk "6 step23 BUILD_STAMP" "$(sed -n '/^### Step 23:/,/^### Step 24:/p' "$P" | grep -c 'BUILD_STAMP' | tr -d ' ')" "3"
|
||||
# 7 blocker 8/9: session 4 fence carries step 13's three files
|
||||
chk "7 session4 fence" "$(sed -n '/^### Session 4:/,/^### Session 5:/p' "$P" | grep -o 'package_plugin.sh\|test_plugin_manifest.py\|`.gitignore`' | sort -u | wc -l | tr -d ' ')" "3"
|
||||
# 8 blocker 16: session 8 fence carries the probe record
|
||||
chk "8 session8 fence probe" "$(sed -n '/^### Session 8:/,/^### Session 9:/p' "$P" | grep -c 'docs/cowork-probe.md' | tr -d ' ')" "1"
|
||||
# 9 blocker 8: .gitignore is a manifest deliverable of step 13
|
||||
chk "9 step13 gitignore manifest" "$(sed -n '/^### Step 13:/,/^### Step 14:/p' "$P" | grep -c '\- \.gitignore\|path: \.gitignore' | tr -d ' ')" "2"
|
||||
# 10 blocker 16: step 31's probe is recorded and gated
|
||||
chk "10 step31 connector-hook" "$(sed -n '/^### Step 31:/,/^### Step 32:/p' "$P" | grep -c 'Connector-hook' | tr -d ' ')" "3"
|
||||
# 11 blocker 15: --check named in every Cowork step that can run it (M2-M6)
|
||||
chk "11 cowork --check" "$(grep -c 'sak_status.py --workspace "\$WS" --check' "$P" | tr -d ' ')" "9"
|
||||
# 12 trekplan high-effort: the Pass 2 marker exists as a heading
|
||||
chk "12 Pass 2 heading" "$(grep -c '^## Adversarial Pass 2' "$P" | tr -d ' ')" "1"
|
||||
echo "----"; echo "PASS=$pass FAIL=$fail"
|
||||
[ "$fail" -eq 0 ]
|
||||
Loading…
Add table
Add a link
Reference in a new issue