fix(gates): close the review findings in the gates and their docs

Two reproduced bugs in check-skill-version-bump:

- The origin/main-tip check fired even when the pushed skill was
  byte-identical to main's tip, so a cherry-pick or backport failed a
  push that ships nothing. The merge-base intersection ea119d8 added
  covers that only when some base carries the content, which a
  criss-cross history gives and a linear one does not. A new
  same_subtree compares tree object ids, so the exemption holds
  whatever route the history took.
- The failure line reported "baseline: none" when the skill was absent
  at every merge-base but present at the tip, and the Fix: line then
  named no version. The author writes the natural 1.0.0 and gets a
  second blocked push. It now falls back to the tip's version.

ADR-0022 is not amended: the documented behaviour does not change, and
ea119d8 set the precedent by fixing the same failure class script-only.

1614bce verified that executables.allow grants are version-blind and
corrected ADR-0019, gates.md and apm.yml, but missed the gate script's
own header and its operator-facing FAIL message, which still told the
reader deployment was silently broken, and gates.md's hook summary,
which still called it a silent-failure guard. All three now match.

Also: README's offline guarantee carries the populated-apm_modules
condition gates.md and AGENTS.md already state; the scripts/ layout row
drops "sync" for the three deleted sync scripts; the check-rtk-prefix
README rationale names the 12 subdirectory READMEs that survive rather
than the skill-root ones this branch deleted; gates.md re-cites its
three head -1 sites by enclosing function per its own :238 rule; and
deploy-manifest drops a pointer to a provider-manifest.sh that has
never existed on main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2
This commit is contained in:
2026-09-20 12:33:50 +00:00
parent 1614bcef23
commit 8cfd54f925
7 changed files with 145 additions and 30 deletions

View File

@@ -633,6 +633,77 @@ write_skill "$F" demo alpha 'version: "1.0.1"' "later body"; commit "$F" F3
expect_fail "an unbumped edit on a criss-cross branch still fails, naming the baseline sha" \
"alpha: 1\.0\.1 -> 1\.0\.1 \(not above merge-base [0-9a-f]{40}\)" "$F"
echo ""
echo "--- 41. a cherry-picked fix identical to main's tip passes ---"
# Case 40 pins the same property — content identical to main's tip ships
# nothing — for a criss-cross history, where the merge-base intersection alone
# already exempts the skill because one base carries that content. This is the
# LINEAR shape, where no base does: the branch was cut before the fix landed on
# main and then cherry-picked it, so the single merge-base predates the fix and
# the skill reaches the tip comparison carrying exactly the tip's version. The
# only escapes would be a spurious 1.0.2 — leaving main with two versions of
# identical content — or a rebase the push does not otherwise need.
#
# C0 alpha 1.0.0
# +-- main: FIX bumps alpha to 1.0.1 (origin/main)
# +-- feature: cherry-picks FIX
F="$(make_fixture)"
(cd "$F" && git checkout -q main)
write_skill "$F" demo alpha 'version: "1.0.1"' "fixed body"; commit "$F" "fix alpha"
FIX_SHA="$(cd "$F" && git rev-parse HEAD)"
# -x: without it the picked commit can come out byte-identical to FIX — same
# tree, same parent, same author and committer second — and git reuses the sha,
# so the branch silently fast-forwards onto main and the case under test is
# gone. The trailer -x adds guarantees a distinct commit.
(cd "$F" && git update-ref refs/remotes/origin/main main && git checkout -q feature \
&& git cherry-pick -x "$FIX_SHA" > /dev/null)
if [[ "$(cd "$F" && git rev-parse HEAD)" != "$FIX_SHA" ]]; then
pass "fixture check: the cherry-pick made a distinct commit, not a fast-forward onto main"
else
fail "fixture check: the branch fast-forwarded onto main, so the tip is the merge-base"
fi
if [[ "$(cd "$F" && git merge-base --all origin/main HEAD | wc -l)" -eq 1 ]]; then
pass "fixture check: the linear history has exactly one merge-base"
else
fail "fixture check: expected one merge-base, got $(cd "$F" && git merge-base --all origin/main HEAD)"
fi
if [[ -z "$(cd "$F" && git diff origin/main HEAD -- plugins)" ]]; then
pass "fixture check: nothing under plugins/ differs between origin/main and the branch"
else
fail "fixture check: plugins/ differs, so this is not the case under test"
fi
expect_pass "a cherry-picked skill identical to main's tip passes without a further bump" "$F"
# The ratchet still holds on the same shape: a further edit is no longer
# identical to the tip, so the tip rule applies again.
write_skill "$F" demo alpha 'version: "1.0.1"' "later body"; commit "$F"
expect_fail "an unbumped edit on top of the cherry-pick still fails against the tip" \
"alpha: 1\.0\.1 -> 1\.0\.1 \(not above origin/main tip\)" "$F"
echo ""
echo "--- 42. the named baseline is the tip when no merge-base carries the skill ---"
# A skill added on main after the branch was cut is absent at every merge-base,
# so only the tip names a version — and the tip's is the version the push is
# held to. Reporting "none" sends the author to the natural 1.0.0 and costs a
# second blocked push on the same mistake.
F="$(make_fixture)"
(cd "$F" && git checkout -q main)
write_skill "$F" demo delta 'version: "3.2.1"' "main's delta"; commit "$F" "add delta on main"
(cd "$F" && git update-ref refs/remotes/origin/main main && git checkout -q feature)
write_skill "$F" demo delta "" "branch delta"; commit "$F" "add delta on branch"
expect_fail "a missing version names the tip's version, not 'none'" \
"delta: metadata\.version missing or not MAJOR\.MINOR\.PATCH at HEAD \(baseline: 3\.2\.1\)" "$F"
expect_fail "the baseline is never reported as none while the tip carries one" \
"delta: metadata\.version missing or not MAJOR\.MINOR\.PATCH at HEAD \(baseline: [0-9]" "$F"
# The same message shape for the SKILL.md-missing branch of the report.
F="$(make_fixture)"
(cd "$F" && git checkout -q main)
write_skill "$F" demo delta 'version: "3.2.1"' "main's delta"; commit "$F" "add delta on main"
(cd "$F" && git update-ref refs/remotes/origin/main main && git checkout -q feature)
mkdir -p "$F/plugins/demo/.apm/skills/delta/references"
echo "ref" > "$F/plugins/demo/.apm/skills/delta/references/x.md"; commit "$F" "delta without SKILL.md"
expect_fail "a missing SKILL.md names the tip's version too" \
"delta: SKILL\.md missing at HEAD \(baseline: 3\.2\.1\)" "$F"
echo ""
echo "Results: $PASS passed, $FAIL failed"
[[ $FAIL -eq 0 ]]