mirror of
https://github.com/zernie/vigiles.git
synced 2026-09-14 20:53:57 +08:00
6532dbf48d
Five defects found dogfooding vigiles on a real consumer repo (zernie/mine — 43 skills,
48 harness files), each measured rather than reasoned about:
1. `exclude` never reached the markdown-refs pass. Measured: 9 broken refs, 8 of them
inside a directory explicitly listed in `exclude`, all 9 still reported. After: 9 → 0.
The consequence was larger than the cause — with no way to reach exit 0 the consumer
set `continue-on-error: true`, and a lint whose exit code is discarded gates nothing.
2. Refs were found by TEXT, per line. Four of six probe inputs classified wrongly
(`ctx.file("OUT")`, `obj.cmd(...)`, a comment, a string), and because the regex ran
per line, any call split across lines was invisible — which had hidden two genuinely
broken refs in this repo's own docs. Now parsed: a ref is a call whose callee is a
bare identifier with a string-literal first argument. `typescript` was already a
runtime dependency. Net: 21 refs → 25, all valid.
3. The script runner was a strict queue. Measured on 48 harness files: 270s → 77s
(3.5x), byte-identical results. The default follows `entry` rather than a new flag:
`test` fans out (free and deterministic by construction — mock model, no API key),
`eval` stays at 1 (real model quota). `stdio: "inherit"` was the actual blocker.
4. Agent path attribution was keyed by name, so with `agents/foo.md` and
`.claude/agents/foo.md` a lethal-trifecta finding was displayed against the wrong
file. Ambiguous names now yield no path instead of an arbitrary one.
5. `compile` emitted invalid YAML. A description containing `: ` produced frontmatter
where `skillContract()` reports `malformed: true, declared: []` — the blessed path
producing the exact defect `frontmatter-valid` exists to report, and punishing anyone
who fixed it by hand with a hash mismatch. Fixed by round-tripping through the same
loader the linter uses, so already-safe values stay byte-identical and no integrity
hash moves.
Plus: all 10 jobs across 6 workflows were unbounded and now carry `timeout-minutes`
sized to measured durations; docs updated in the pages that own each defect.
Gates: vitest 3186 passed - lint 0 errors - prettier clean - api:check no drift - build.
CI: all 7 jobs green.
83 lines
3.4 KiB
YAML
83 lines
3.4 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
|
|
permissions:
|
|
contents: write
|
|
issues: write
|
|
pull-requests: write
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: ubuntu-latest
|
|
# Bounded 2026-08-19. Every job in this repository was unbounded, so a hung one
|
|
# ran to GitHub's six-hour ceiling — the one failure mode a green checkmark
|
|
# cannot show you, because it does not fail, it bills. Sizes are ~3-4x the
|
|
# MEASURED duration on this repo's own runs, quoted per job so a later edit can
|
|
# see where the number came from instead of guessing again.
|
|
# not measured; publishes to npm, so bounded generously but bounded.
|
|
timeout-minutes: 20
|
|
# Skip release on commits that don't affect the package
|
|
if: "!contains(github.event.head_commit.message, '[skip ci]')"
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
# 🔴 20 → 22 on 2026-08-16, because the release job DIED on this line and took a
|
|
# major with it. `semantic-release` refuses to start on Node 20:
|
|
#
|
|
# [semantic-release]: node version ^22.14.0 || >= 24.10.0 is required. Found v20.20.2.
|
|
#
|
|
# It fails BEFORE analysing a single commit, so `fix(release)!:` in #152 — the commit
|
|
# that repaired the preset so `!` means major at all — never became v16.0.0. npm sat
|
|
# at 15.4.1 while `main` carried breaking changes, which is the exact condition #152
|
|
# existed to end.
|
|
#
|
|
# ⚠️ THE REAL DEFECT IS NOT THIS NUMBER. `semantic-release` is not in package.json at
|
|
# all, so `npx semantic-release` resolves the newest published version on every run.
|
|
# The release pipeline therefore changes behaviour with no commit to this repository:
|
|
# run 132 passed at 19:30 and run 133 failed at 21:24 on the same config, because a
|
|
# release in between dropped Node 20. Bumping the runtime unblocks today and leaves
|
|
# that open — pinning the tool as a devDependency is the fix that closes it.
|
|
node-version: "22"
|
|
cache: "npm"
|
|
|
|
- run: npm ci
|
|
|
|
- name: Build
|
|
run: npm run build
|
|
|
|
- name: Release
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
run: npx semantic-release
|
|
|
|
- name: Update floating major-version tag for the Action
|
|
# Marketplace consumers pin `uses: zernie/vigiles@v1`. Point that
|
|
# floating tag at the newest released vX.Y.Z so @v1 always tracks the
|
|
# latest compatible release. Idempotent: a no-op when already current.
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
git fetch --tags --force
|
|
latest="$(git tag --list 'v[0-9]*.[0-9]*.[0-9]*' --sort=-v:refname | head -n1)"
|
|
if [ -z "$latest" ]; then
|
|
echo "No version tags yet — skipping major-tag update."
|
|
exit 0
|
|
fi
|
|
major="${latest%%.*}" # v1.2.3 -> v1
|
|
if [ "$(git rev-parse -q --verify "refs/tags/$major" || true)" = "$(git rev-parse "$latest")" ]; then
|
|
echo "$major already points at $latest — nothing to do."
|
|
exit 0
|
|
fi
|
|
echo "Pointing $major at $latest"
|
|
git tag -f "$major" "$latest"
|
|
git push origin -f "refs/tags/$major"
|