fix(gates): hold skill versions above main's tip as well as the merge-base

Why: two branches that both bump a skill 1.0.0 -> 1.0.1 with different
content merge without a conflict, and each passed the gate against its own
merge-base, so main could ship two changes under one version.

Implementation Notes:
- check-skill-version-bump requires the pushed version to exceed both the
  merge-base and the main tip; failures name the baseline they missed.
- Presence is read from the tree, so a blob missing from a partial clone is
  a read failure instead of a silently exempt "new" skill.
- A leading UTF-8 BOM no longer reads as a missing version.
- Version parts reject leading zeros in all three validators
  (check-skill-version-bump, skill-size-check, factory-audit).
- New tests cover equal bumps, moved files, major/minor ordering, bad refs,
  unreadable blobs, mode-only changes, symlinks and tag peeling.

Impact: ADR-0022 amended (reverses "not main's current tip"); gates.md
updated to match, including pre-commit 4.6.1's exact ref selection.

ADR: 0022
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-16 11:24:08 +00:00
parent b426460f75
commit 1d40544075
8 changed files with 446 additions and 87 deletions

View File

@@ -899,6 +899,45 @@ else
pass "the SUGGESTION survives LC_ALL=C, streams pinned to UTF-8"
fi
# ---------------------------------------------------------------------------
# metadata.version shape: no leading zeros, matching check-skill-version-bump
# ---------------------------------------------------------------------------
echo ""
echo "--- metadata.version with a leading zero is malformed ---"
for version_case in "1.0.08:malformed" "01.0.1:malformed" "1.0.10:valid" "0.1.0:valid"; do
version="${version_case%%:*}"
expected="${version_case##*:}"
VERSION_SKILL="$TMPDIR/version-$version"
mkdir -p "$VERSION_SKILL"
cat > "$VERSION_SKILL/SKILL.md" <<VERSIONEOF
---
name: version-skill
description: A valid skill description that is well within the limit.
metadata:
version: "$version"
---
## Step 1
Do the thing.
VERSIONEOF
set +e
VERSION_OUT="$("$SCRIPT" "$VERSION_SKILL/SKILL.md" 2>&1)"
VERSION_STATUS=$?
set -e
if [[ "$expected" == malformed ]]; then
if [[ $VERSION_STATUS -ne 0 && "$VERSION_OUT" == *"metadata.version is malformed ('$version')"* ]]; then
pass "'$version' is rejected as malformed"
else
fail "'$version' was not rejected as malformed (exit $VERSION_STATUS): ${VERSION_OUT:-<empty>}"
fi
elif [[ "$VERSION_OUT" == *"metadata.version is malformed"* ]]; then
fail "'$version' was wrongly rejected as malformed: $VERSION_OUT"
else
pass "'$version' is accepted"
fi
done
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]