feat(ci): gate the vendored pi-extensions skill floor, and bake python3-yaml
Followsecfd2fc, which refreshed the stale floor by hand. A one-off refresh fixes the symptom; this makes the drift impossible to reintroduce silently. scripts/check-skill-floor.sh compares the repo floor (rootfs/usr/local/share/pi-devbox/skills/pi-extensions/) against the package repo it is a snapshot of, wired in as a new `skill-floor` job in lint.yml. DIRECTORY hash, not `sha256sum SKILL.md`, using the same tree_sha256 pipeline Dockerfile.variant uses for skillset_snapshot_tree_sha256 and for the reason already documented there: a file-only compare answers "did this one file change", not "is this the same skill". Verified by NEGATIVE CONTROL rather than asserted -- with SKILL.md left byte-identical and only evaluate-extension-usage.py edited, the directory check fails (rc=1) where a file-only compare would have passed. Seven behaviour tests, each with its expected rc written down before running: in-sync via local dir (0), in-sync via anonymous remote clone (0), missing --package-dir (2), bad argument (2), content drift (1), the sibling-file case (1), and --warn-only over drift (0). Exit codes 0 in sync / 1 drift / 2 cannot-run, matching scripts/lint-shell.sh: a gate that cannot run must not pass, so an unreachable package repo is a red 2 and never a green tick. A ref with no skill/ is NOT drift -- that is the documented fallback -- but it emits ::warning:: because it is precisely the condition under which the floor ships. Gating on another repo is normally a smell. It is proportionate here because the check can only fire when skill/ itself changed, which is exactly when the floor has gone stale; pi-extensions commits that leave skill/ alone cannot turn this red. It also needs no secret: pi-extensions is anonymously clonable (verified with `git ls-remote` and no credentials), so it cannot start failing when a token expires. Also bakes python3-yaml (552 KB, zero extra deps) into Dockerfile.base. This is the shellcheck story repeating exactly: scripts/check-workflow-shell.sh -- the guard against the Gitea sh/dash footgun that broke resolve-versions (ed49b8d) and promote-base-latest (b7197e8) -- hard-exits with "python3 yaml module missing", so a gate this repo already owns could not be run locally by anyone. lint.yml installing it explicitly in CI was the evidence. Found while wiring the job above: the guard could not be run before pushing. CHANGELOG Unreleased updated for both this andecfd2fc, including an explicit note on what is NOT fixed -- the silent-fallback half still has no manifest flag recording which copy was served. Verified locally with every gate this repo owns, all green: lint-shell.sh (15 files clean), check-workflow-shell.sh, check-base-hash.sh, actionlint 1.7.7 (pinned, same version as CI), hadolint 2.14.0, and the new check itself.
This commit is contained in:
@@ -137,3 +137,38 @@ jobs:
|
||||
|
||||
- name: Run hadolint
|
||||
run: hadolint Dockerfile.base Dockerfile.variant
|
||||
|
||||
skill-floor:
|
||||
# Gate the VENDORED pi-extensions skill snapshot in rootfs/ against the
|
||||
# package repo it is a snapshot of. Its own job rather than a step in
|
||||
# `actionlint`, so "the floor is stale" is a distinct red name in the runs
|
||||
# list instead of being buried in a lint job that is about something else.
|
||||
#
|
||||
# The gap it closes, measured 2026-09-10: the floor sat at 34284 B, untouched
|
||||
# since fa04d20 (2026-07-30), while the package copy was 38973 B.
|
||||
# Dockerfile.variant copies the fresh package copy over the SERVED path but
|
||||
# never writes back to the floor, so nothing in the repo ever noticed. That
|
||||
# matters because the floor is a FALLBACK: the copy is guarded by
|
||||
# `if [ -f /opt/pi-extensions/skill/SKILL.md ]`, so a build whose clone
|
||||
# yields no skill/ ships the vendored snapshot and still goes green, with no
|
||||
# manifest flag or label saying which copy was served.
|
||||
#
|
||||
# Gating on another repo is normally a smell; it is proportionate here
|
||||
# because the check compares the skill DIRECTORY hash, so it can only fire
|
||||
# when that directory actually changed — which is exactly when the floor has
|
||||
# gone stale. pi-extensions commits that leave skill/ alone cannot turn this
|
||||
# red. No secret is needed either: the repo is anonymously clonable (verified
|
||||
# 2026-09-10 with `git ls-remote` and no credentials), so this cannot start
|
||||
# failing when a token expires.
|
||||
#
|
||||
# Exit codes are 0 in sync / 1 drift / 2 cannot-run, matching
|
||||
# scripts/lint-shell.sh: a gate that cannot run must not pass, so an
|
||||
# unreachable package repo is a red 2 rather than a green tick.
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: catthehacker/ubuntu:act-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Vendored pi-extensions skill floor matches the package
|
||||
run: bash scripts/check-skill-floor.sh
|
||||
|
||||
Reference in New Issue
Block a user