plans/025-skills-docs-drift-guard.md
skills/ drifting from docs/Executor instructions: Follow this plan step by step. Run every verification command and confirm the expected result. If anything in "STOP conditions" occurs, stop and report. When done, update the status row in
plans/README.md.Drift check (run first):
git diff --stat c63cb120..HEAD -- skills/ scripts/ .github/workflows/On a mismatch with the excerpts below, treat it as a STOP condition.
c63cb120, 2026-07-10skills/slidev/** is an agent-facing reference generated from docs/ and is
shipped to every user inside @slidev/cli (scripts/publish.mjs:4 copies
skills into packages/slidev/skills). Its provenance is recorded in
skills/GENERATION.md as SHA 9d300814 / v52.11.3 — but the repo is v52.16.0
with dozens of docs/ commits since, and the only sync mechanism is a manual
human checklist. So stale guidance ships to users' agents invisibly. This plan
adds an automated drift guard: CI fails when docs/ has advanced past the
SHA the skills were generated from, forcing a re-sync + provenance bump. (It does
NOT auto-regenerate — that generator is a separate, larger effort.)
skills/GENERATION.md records provenance in prose:
**Short SHA**: \9d300814` (:10`):194-196)Current SHA: 9d300814 (final line)
There is no machine-readable marker and no CI check.scripts/publish.mjs:4: await fs.copy('skills', 'packages/slidev/skills', { overwrite: true }).scripts/ already contains Node/zx scripts (e.g. publish.mjs,
update-versions.mjs), so adding a script is idiomatic..github/workflows/ (see test.yml).| Purpose | Command | Expected |
|---|---|---|
| Run the new check | node scripts/check-skills-drift.mjs | exit 0 when in sync; non-zero + message when drifted |
| YAML sanity | pnpm dlx js-yaml .github/workflows/<file>.yml | parses |
(No build/deps needed; the script uses git + Node fs.)
In scope:
skills/GENERATION.md (add a machine-readable provenance marker)scripts/check-skills-drift.mjs (create).github/workflows/ (add a job/step that runs the check)Out of scope:
skills/slidev/** content (do not hand-edit generated files).publish.mjs.ci/skills-drift-guard.ci: fail when skills drift from docs.Add a single unambiguous line to skills/GENERATION.md (near the top) that the
script parses, seeded with the currently-recorded SHA:
<!-- skills-generated-from: 9d300814 -->
Keep the existing human-readable fields too; this marker is the source of truth for the check.
scripts/check-skills-drift.mjsThe script:
skills/GENERATION.md (regex on
skills-generated-from:\s*([0-9a-f]+)); error if absent.git rev-list --count <sha>..HEAD -- docs/ (via node:child_process
execFileSync('git', [...]) — argv array, no shell).0, print "skills in sync with docs" and exit 0.> 0, print the list (git diff --name-only <sha>..HEAD -- docs/) and a
remediation message ("Re-sync skills/ per skills/GENERATION.md and update
the skills-generated-from marker to the current HEAD"), then exit 1.
Handle the case where <sha> is not an ancestor (e.g. shallow CI clone):
detect the failure of git rev-list and exit 0 with a warning rather than
hard-failing CI on a fetch-depth issue.Match the style of existing scripts/*.mjs (ESM, top-level await ok).
Add a lightweight job (or a step in an existing job) that runs
node scripts/check-skills-drift.mjs. Because it needs history for
git rev-list, set the checkout to full depth:
skills-drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: actions/setup-node@v6
with:
node-version: lts/*
- name: Check skills/docs drift
run: node scripts/check-skills-drift.mjs
Verify:
node scripts/check-skills-drift.mjs runs and exits non-zero today
(docs have advanced past 9d300814), printing the changed docs files — that is
the guard working. (Do NOT "fix" it by editing skills in this plan; the point is
to surface the drift.)docs/ files. Temporarily set the marker to HEAD's short SHA
and re-run → exits 0. Restore the real recorded SHA afterward.skills/GENERATION.md has a skills-generated-from: markerscripts/check-skills-drift.mjs exists, uses argv-based git (no shell), and handles the non-ancestor/shallow case gracefullyfetch-depth: 0git status)plans/README.md status row updatedStop and report if:
docs/ tree) and report
the approach change.skills-generated-from: marker (and the
human fields) to the current HEAD; the guard then goes green until docs move
again.