{ "name": "doc-drift", "description": "Compare a documented version record (a changelog) against the source-of-truth git tags and report any drift. Reads and reports only — never edits the document, never creates, moves, or deletes a tag.", "intent": { "guarantee": "This skill only reads the changelog and the tag list and reports drift — it never edits the document or touches any tag", "forbidden": [ "git tag", "git push", "git commit", "git add", "edit the changelog", "create or move any tag" ] }, "capabilities": [ { "kind": "tool", "name": "Read" }, { "kind": "tool", "name": "Grep" }, { "kind": "tool", "name": "Glob" }, { "kind": "tool", "name": "AskUserQuestion" }, { "kind": "bash", "verb": "git for-each-ref", "scope": "refs/tags*" }, { "kind": "bash", "verb": "git log", "scope": "*" }, { "kind": "bash", "verb": "git describe", "scope": "*" }, { "kind": "bash", "verb": "git status", "scope": "*" } ], "params": [ { "name": "doc", "description": "the documented version record to check", "default": "CHANGELOG.md" }, { "name": "tag_glob", "description": "the tag pattern that is the source of truth", "default": "v*.*.*" } ], "steps": [ { "index": 0, "title": "Read the documented versions", "body": "Read the doc param (default CHANGELOG.md) and extract the set of versions it records — the section headings of the form `## [x.y.z]` or equivalent. Keep them in document order. Do not edit the file." }, { "index": 1, "title": "List the source-of-truth tags", "body": "List the release tags with the read-only command below — `git for-each-ref`, never `git tag` (which can create a tag). Filter to the tag_glob pattern (default v*.*.*). This set is the source of truth for what was actually released.", "runs": [ "git for-each-ref --sort=-version:refname --format '%(refname:short)' refs/tags", "git describe --tags --always" ] }, { "index": 2, "title": "Diff the two sets", "body": "Compute the symmetric difference: tags with no changelog section (released but undocumented) and changelog sections with no tag (documented but unreleased, e.g. a stale or premature entry). Normalize the `v` prefix so `v1.2.3` and `1.2.3` match." }, { "index": 3, "title": "Classify each drift", "body": "For each mismatch, classify it: missing-changelog-entry (a tag with no section — the more serious, a shipped release with no record), or unreleased-section (a section with no tag — usually an in-progress or premature entry). Note an Unreleased/building section separately; it is expected, not drift." }, { "index": 4, "title": "Report, never reconcile", "body": "Print a table of the drift with its classification, plus a one-line summary (clean, or N drifts). Recommend the fix in prose (add a section, cut a tag) but never apply it: do not edit the changelog and do not create, move, or delete a tag. The operator reconciles." } ], "output_format": "Print a drift table (version, classification, note) and a one-line summary. State explicitly that nothing was edited and no tag was touched.", "maps_to_workflow": "doc-drift" }