fix(gates): close six PR #135 review findings in gates and their tests

B1: check-skill-version-bump.sh resolves every merge-base with `git merge-base
--all` instead of the single base git happens to pick. A criss-cross history has
two, so the verdict turned on that choice: a skill byte-identical to main's tip
could still be reported "not above merge-base" / "not above main tip" and fail a
push that should pass. A skill now counts as changed only when it differs from
EVERY base, and its version must exceed the version at every base it exists at
as well as at the main tip; with more than one base the failure names which one.
Case 40 in tests/test-skill-version-bump.sh builds the criss-cross fixture and
pins both directions.

B2: check-apm-current.sh no longer assumes the remote default branch is `main`
when origin/HEAD is unset. A checkout whose default is `master` was standing on
its default branch and being told "this is a feature branch, so discard it" --
to throw away a real lock update. With origin/HEAD unset nothing is asserted and
the neutral advice stands. tests/test-apm-current-hook.sh covers the unset case
on both `main` and `master`.

#4: the required-frontmatter checks folded into skill-size-check.sh by c8a7c9e
were untested apart from the leading-zero shape -- mutating the missing-version
ERROR into a no-op left every suite green. tests/test-adr0020-frontmatter.sh now
pins name presence and non-emptiness, metadata.version presence and semver
shape, and the four grep defects the deleted test-skill-frontmatter.sh named.

#5: nothing asked whether a Vale rule still MATCHES anything -- rewriting
CompositionNote.yml's tokens to match nothing left test-vale-wrap.sh at 63/63.
Case 35 enumerates the rule files under the Kyberforge* style directories at run
time, requires an alert from each on its own fixture, and fails when a
discovered rule has no fixture row. The stale comment at case 31 is corrected.

#6: tests/run-tests.sh --strict exited 0 when discovery found no test-*.sh at
all; strictness only ever acted on skips, and with no suites there were none. It
now cross-checks the git index the way run-bats.sh does and fails
unconditionally on an empty set, naming the search root.

N9: the skill-size-check hook description in .pre-commit-config.yaml covered
only the size, context-budget and boundary-target gates. It now also names the
required frontmatter fields, matching docs/spec/gates.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2
This commit is contained in:
2026-09-19 21:08:10 +00:00
parent e62188c3c3
commit ea119d83b0
9 changed files with 693 additions and 49 deletions

View File

@@ -703,6 +703,74 @@ else
pass "a root under .claude/worktrees/ runs its own suites and skips nested worktrees"
fi
# --- 13. Discovering ZERO test-*.sh files is a hard error, not a green run ---
# The quietest vacuous pass in the dispatcher, and the one --strict did not
# reach: strictness only ever turned SKIPS into failures, so with no suites to
# skip there was nothing for it to act on. The loops iterated zero times, the
# run printed `Summary: 0 passed, 0 skipped, 0 failed` and exited 0 -- from the
# run-tests pre-push hook, which prints nothing for a passing hook, that is
# indistinguishable from every suite passing. A wrong TEST_DIR, a mistyped find
# pattern, an exclusion that grew to swallow tests/, and a gutted checkout all
# land here. tests/run-bats.sh has guarded its own discovery this way since it
# hit the same hole; this is the sibling.
#
# The bats runner is the healthy stub, so the only thing wrong with the fixture
# is that it has no case scripts -- a failure here cannot be the bats leg.
echo ""
echo "--- discovering zero test-*.sh files fails the run and names the search root ---"
DIR13="$(make_fake_repo)"
FIXTURES+=("$DIR13")
install_healthy_bats_runner "$DIR13"
run_fake "$DIR13"
if [[ $FAKE_RC -eq 0 ]]; then
fail "an empty search root exited 0 — a run that verified nothing reports the same as a run that verified everything: $FAKE_OUT"
elif ! grep -q "found 0 test-\*\.sh file(s)" <<< "$FAKE_OUT"; then
fail "an empty search root failed without saying that nothing was discovered: $FAKE_OUT"
elif ! grep -qF "$DIR13/cases" <<< "$FAKE_OUT"; then
fail "the zero-discovery error did not name the root it searched, which is the one fact needed to fix it: $FAKE_OUT"
elif grep -q "^=== Summary:" <<< "$FAKE_OUT"; then
fail "an empty search root still printed a summary line, so a reader scanning for the verdict sees a green one: $FAKE_OUT"
else
pass "zero discovered test-*.sh files fails the run, names the search root, and prints no summary"
fi
# And under --strict too. Asserted separately because the ONLY lever --strict
# had was the skip list, so "it fails now" and "it fails under the gate's own
# invocation" were genuinely different questions here.
echo ""
echo "--- ... and under --strict, which previously had no lever on this at all ---"
DIR13B="$(make_fake_repo)"
FIXTURES+=("$DIR13B")
install_healthy_bats_runner "$DIR13B"
run_fake "$DIR13B" --strict
if [[ $FAKE_RC -eq 0 ]]; then
fail "an empty search root exited 0 under --strict, the invocation the run-tests pre-push hook uses: $FAKE_OUT"
elif grep -q "found 0 test-\*\.sh file(s)" <<< "$FAKE_OUT"; then
pass "--strict also fails a run that discovered nothing"
else
fail "--strict failed an empty search root for some other reason: $FAKE_OUT"
fi
# The control: one discovered case is enough to get past the guard, so the two
# cases above fail on the count and not on something else the fixture lacks.
echo ""
echo "--- ... while a single discovered case still passes ---"
DIR13C="$(make_fake_repo)"
FIXTURES+=("$DIR13C")
install_healthy_bats_runner "$DIR13C"
add_case "$DIR13C" test-one.sh <<'EOF'
#!/usr/bin/env bash
echo "one case ran"
EOF
run_fake "$DIR13C"
if [[ $FAKE_RC -ne 0 ]]; then
fail "a fixture with exactly one case failed: $FAKE_OUT"
elif grep -q "found 0 test-\*\.sh file(s)" <<< "$FAKE_OUT"; then
fail "the zero-discovery guard fired on a root that has one case script: $FAKE_OUT"
else
pass "one discovered case script is enough to get past the zero-discovery guard"
fi
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]