task check goes red on a dev checkout whose tags are stale, not on a real fault #34

Closed
opened 2026-08-29 08:06:14 +00:00 by mathias · 1 comment
Owner

Symptom

On a working checkout, immediately after git pull --rebase brings in the tagger's chore(release): plugin.json version X commit:

$ task check
ERROR: plugin.json version (0.9.0) != latest tag (0.8.5)
exit 201

Nothing is wrong. v0.9.0 exists on the remote; this checkout has not fetched it. git fetch --tags && task check → exit 0.

Hit three times in one session (2026-08-29) while working the backlog, because the loop is: push → CI tags and pushes the bump commit → pull → check is red until you also fetch tags.

Cause

Taskfile.yml check step 4 asserts equality:

if [ -n "$tag_v" ] && [ "$manifest_v" != "$tag_v" ]; then

git describe --tags is local-only, so tag_v is whatever this checkout last fetched.

What the assertion is actually for

Claude Code gates plugin updates on plugin.json's version. The failure it must catch is the manifest not moving — a release tag with a manifest still on the old number, so no installed host ever sees the update. That is manifest < tag.

manifest > tag is the normal state on any checkout between the bump commit and a tag fetch, and it is also the normal state inside CI for the tagger's own commit. It is not a fault.

Fix

Compare order, not equality: fail when the manifest is behind the latest known tag, and stay quiet when it is ahead. bin/doctor already grew a newer_version helper (major.minor.patch via awk) in #30 that can be reused rather than reimplemented — which argues for extracting it to bin/ where both can call it, with the tests coming along.

Definition of done

task check on a checkout with stale tags exits 0; task check with plugin.json behind the latest tag still exits non-zero and names both versions.

## Symptom On a working checkout, immediately after `git pull --rebase` brings in the tagger's `chore(release): plugin.json version X` commit: ``` $ task check ERROR: plugin.json version (0.9.0) != latest tag (0.8.5) exit 201 ``` Nothing is wrong. `v0.9.0` exists on the remote; this checkout has not fetched it. `git fetch --tags && task check` → exit 0. Hit three times in one session (2026-08-29) while working the backlog, because the loop is: push → CI tags and pushes the bump commit → pull → check is red until you also fetch tags. ## Cause `Taskfile.yml` check step 4 asserts **equality**: ```sh if [ -n "$tag_v" ] && [ "$manifest_v" != "$tag_v" ]; then ``` `git describe --tags` is local-only, so `tag_v` is whatever this checkout last fetched. ## What the assertion is actually for Claude Code gates plugin updates on `plugin.json`'s `version`. The failure it must catch is the manifest **not moving** — a release tag with a manifest still on the old number, so no installed host ever sees the update. That is `manifest < tag`. `manifest > tag` is the normal state on any checkout between the bump commit and a tag fetch, and it is also the normal state inside CI for the tagger's own commit. It is not a fault. ## Fix Compare order, not equality: fail when the manifest is **behind** the latest known tag, and stay quiet when it is ahead. `bin/doctor` already grew a `newer_version` helper (major.minor.patch via awk) in #30 that can be reused rather than reimplemented — which argues for extracting it to `bin/` where both can call it, with the tests coming along. ## Definition of done `task check` on a checkout with stale tags exits 0; `task check` with `plugin.json` behind the latest tag still exits non-zero and names both versions.
Author
Owner

Fixed in 1573732. Gate green on run #36 (the first run after the tagger fix; #33's own run died in the tag job on the queue race described in #22, not in the gate).

task check now fails only when the manifest is behind the newest tag it knows about, and stays quiet when it is ahead — the normal state between the tagger's bump commit and a tag fetch.

The comparison moved to bin/newer-version, shared with bin/doctor rather than existing twice, with seven cases including the lexical trap (0.8.10 beats 0.8.9) and a missing component counting as zero.

Mutation-verified:

manifest 0.1.0 vs tag v0.9.0 → exit 201, "plugin.json version (0.1.0) is behind the latest tag (0.9.0)"
manifest 9.9.9 vs tag v0.9.0 → exit 0

It immediately earned itself

An hour after landing, three queued runs failed to push their manifest bump and v0.10.0 got tagged with plugin.json still reading 0.9.0 — a release no installed host would ever see, which is exactly the fault the equality check was nominally guarding and which the old equality check would have reported identically to a harmless stale-tag checkout. Ordering made the difference between noise and a signal: main was red for the right reason, and stayed red until d7775aa fixed the tagger.

Fixed in `1573732`. Gate green on run [#36](https://git.d-ma.be/mathias/skills/actions/runs/4853) (the first run after the tagger fix; #33's own run died in the `tag` job on the queue race described in #22, not in the gate). `task check` now fails only when the manifest is **behind** the newest tag it knows about, and stays quiet when it is ahead — the normal state between the tagger's bump commit and a tag fetch. The comparison moved to `bin/newer-version`, shared with `bin/doctor` rather than existing twice, with seven cases including the lexical trap (`0.8.10` beats `0.8.9`) and a missing component counting as zero. Mutation-verified: ``` manifest 0.1.0 vs tag v0.9.0 → exit 201, "plugin.json version (0.1.0) is behind the latest tag (0.9.0)" manifest 9.9.9 vs tag v0.9.0 → exit 0 ``` ## It immediately earned itself An hour after landing, three queued runs failed to push their manifest bump and `v0.10.0` got tagged with `plugin.json` still reading `0.9.0` — a release no installed host would ever see, which is exactly the fault the equality check was nominally guarding and which the *old* equality check would have reported identically to a harmless stale-tag checkout. Ordering made the difference between noise and a signal: main was red for the right reason, and stayed red until `d7775aa` fixed the tagger.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/skills#34