Residual gap in the check shipped for #30, found while verifying koala at the end of the backlog sweep.
What works
bin/doctor compares the version recorded in installed_plugins.json against the newest manifest already on the host — the active checkout plus any marketplace clone. On koala right now:
Correct, and it caught the real 0.6.0-vs-0.8.4 skew earlier today.
What it cannot see
v0.13.0 is the latest tag on main. This host is at 0.12.1 everywhere — checkout, marketplace clone, installed plugin — so all three agree and doctor reports clean. The host is one release behind and says nothing.
That is the same class of silence #30 was filed about, one level up: not "the plugin is older than the checkout" but "everything here is older than the repo".
Why it is not simply a bug
bin/doctor does no network I/O, deliberately — it runs in a SessionStart hook where latency shows, and its header says so: "It does no network I/O and never shells out to git for a fetch." Detecting this needs either a fetch or a cached answer from something that does fetch.
Options, none obviously right
Leave it.task update fast-forwards and re-wires; the gap only bites a host nobody has updated. Costs nothing, catches nothing.
Opt-in flag.doctor --online does one git ls-remote --tags and reports; the session hook keeps calling the offline form. Honest, but a check nobody runs by default is close to option 1.
Cache the answer. Whatever already fetches on this host (the plugin's own update path, or a scheduled job) writes the latest known tag to a file; doctor reads it and reports staleness plus the file's age. Keeps doctor offline and still catches the case — but adds a second thing that can be stale, which is how this whole class starts.
Leaning 2, with the flag wired into a scheduled per-host job rather than into the session hook.
Also noticed
Something re-ran install.sh with the defaultSKILLS_CHECKOUT_DIR at 14:05 today, which fast-forwarded ~/.local/share/skills and re-pointed every link there, replacing the wiring an earlier task install had made from ~/dev/skills. That is arguably correct — the default is documented as load-bearing — but it means the canonical checkout on a host can move without anyone asking for it, and ~/dev/skills silently stops being what any harness loads. Worth confirming what ran it before deciding whether it is a feature.
Residual gap in the check shipped for #30, found while verifying koala at the end of the backlog sweep.
## What works
`bin/doctor` compares the version recorded in `installed_plugins.json` against the newest manifest already **on the host** — the active checkout plus any marketplace clone. On koala right now:
```json
{"checkout":"/home/mathias/.local/share/skills","expected":41,
"plugin":{"installed":"0.12.1","available":"0.12.1"},"findings":[]}
```
Correct, and it caught the real 0.6.0-vs-0.8.4 skew earlier today.
## What it cannot see
`v0.13.0` is the latest tag on `main`. This host is at `0.12.1` everywhere — checkout, marketplace clone, installed plugin — so all three agree and doctor reports clean. The host is one release behind and says nothing.
That is the *same class* of silence #30 was filed about, one level up: not "the plugin is older than the checkout" but "everything here is older than the repo".
## Why it is not simply a bug
`bin/doctor` does no network I/O, deliberately — it runs in a SessionStart hook where latency shows, and its header says so: *"It does no network I/O and never shells out to git for a fetch."* Detecting this needs either a fetch or a cached answer from something that does fetch.
## Options, none obviously right
1. **Leave it.** `task update` fast-forwards and re-wires; the gap only bites a host nobody has updated. Costs nothing, catches nothing.
2. **Opt-in flag.** `doctor --online` does one `git ls-remote --tags` and reports; the session hook keeps calling the offline form. Honest, but a check nobody runs by default is close to option 1.
3. **Cache the answer.** Whatever already fetches on this host (the plugin's own update path, or a scheduled job) writes the latest known tag to a file; doctor reads it and reports staleness plus the file's age. Keeps doctor offline and still catches the case — but adds a second thing that can be stale, which is how this whole class starts.
Leaning 2, with the flag wired into a scheduled per-host job rather than into the session hook.
## Also noticed
Something re-ran `install.sh` with the **default** `SKILLS_CHECKOUT_DIR` at 14:05 today, which fast-forwarded `~/.local/share/skills` and re-pointed every link there, replacing the wiring an earlier `task install` had made from `~/dev/skills`. That is arguably correct — the default is documented as load-bearing — but it means the canonical checkout on a host can move without anyone asking for it, and `~/dev/skills` silently stops being what any harness loads. Worth confirming what ran it before deciding whether it is a feature.
One git ls-remote against origin. Belongs in a scheduled per-host job, not the SessionStart hook — a check that costs latency on every session start is a check someone eventually disables.
Design calls, each for a reason
Order, not equality. A host ahead of the newest tag is the normal state between a release commit and its tag landing. Same reasoning as task check's ordering rule (#34), reusing bin/newer-version.
An unreachable remote is a WARN naming itself, not a staleness FAIL. "I could not check" and "you are behind" are different answers, and collapsing them makes a network blip look like a stale library — the exact category error #38 was filed about, one level down.
The remote URL is never printed. A remote rewritten by url.insteadOf expands into a live token; that has leaked a credential on koala before.
The default run's silence is now a test, not a comment. One of the five fixture cases stubs a newer remote tag and asserts the default invocation ignores it, so the "no network I/O" promise in doctor's header is enforced rather than trusted.
Live, on the host that motivated it
$ bin/doctor --online
FAIL behind: this host has 0.12.1; origin has released 0.13.4 —
run 'task update' and '/plugin update skills@mathias'
$ bin/doctor
skills doctor: clean — 41 skills
Same host, same moment: clean offline, correctly red online. That is the gap this issue described, now visible on demand.
The second observation stands unresolved
Something re-ran install.sh with the default SKILLS_CHECKOUT_DIR at 14:05, which re-pointed every link from ~/dev/skills to ~/.local/share/skills. Still true — the doctor output above names ~/.local/share/skills as the checkout. It is arguably correct behaviour (the default is documented as load-bearing) but it means the canonical checkout can move without anyone asking, and a ~/dev/skills you are actively editing silently stops being what any harness loads. Worth knowing what triggered it before deciding whether that is a feature; not filed separately yet.
Shipped in `b2af4e1` — option 2, the opt-in flag.
```bash
task doctor -- --online # or bin/doctor --online
```
One `git ls-remote` against origin. Belongs in a scheduled per-host job, not the SessionStart hook — a check that costs latency on every session start is a check someone eventually disables.
## Design calls, each for a reason
**Order, not equality.** A host *ahead* of the newest tag is the normal state between a release commit and its tag landing. Same reasoning as `task check`'s ordering rule (#34), reusing `bin/newer-version`.
**An unreachable remote is a WARN naming itself, not a staleness FAIL.** "I could not check" and "you are behind" are different answers, and collapsing them makes a network blip look like a stale library — the exact category error #38 was filed about, one level down.
**The remote URL is never printed.** A remote rewritten by `url.insteadOf` expands into a live token; that has leaked a credential on koala before.
**The default run's silence is now a test, not a comment.** One of the five fixture cases stubs a newer remote tag and asserts the *default* invocation ignores it, so the "no network I/O" promise in doctor's header is enforced rather than trusted.
## Live, on the host that motivated it
```
$ bin/doctor --online
FAIL behind: this host has 0.12.1; origin has released 0.13.4 —
run 'task update' and '/plugin update skills@mathias'
$ bin/doctor
skills doctor: clean — 41 skills
```
Same host, same moment: clean offline, correctly red online. That is the gap this issue described, now visible on demand.
## The second observation stands unresolved
Something re-ran `install.sh` with the default `SKILLS_CHECKOUT_DIR` at 14:05, which re-pointed every link from `~/dev/skills` to `~/.local/share/skills`. Still true — the doctor output above names `~/.local/share/skills` as the checkout. It is arguably correct behaviour (the default is documented as load-bearing) but it means the canonical checkout can move without anyone asking, and a `~/dev/skills` you are actively editing silently stops being what any harness loads. Worth knowing what triggered it before deciding whether that is a feature; not filed separately yet.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Residual gap in the check shipped for #30, found while verifying koala at the end of the backlog sweep.
What works
bin/doctorcompares the version recorded ininstalled_plugins.jsonagainst the newest manifest already on the host — the active checkout plus any marketplace clone. On koala right now:Correct, and it caught the real 0.6.0-vs-0.8.4 skew earlier today.
What it cannot see
v0.13.0is the latest tag onmain. This host is at0.12.1everywhere — checkout, marketplace clone, installed plugin — so all three agree and doctor reports clean. The host is one release behind and says nothing.That is the same class of silence #30 was filed about, one level up: not "the plugin is older than the checkout" but "everything here is older than the repo".
Why it is not simply a bug
bin/doctordoes no network I/O, deliberately — it runs in a SessionStart hook where latency shows, and its header says so: "It does no network I/O and never shells out to git for a fetch." Detecting this needs either a fetch or a cached answer from something that does fetch.Options, none obviously right
task updatefast-forwards and re-wires; the gap only bites a host nobody has updated. Costs nothing, catches nothing.doctor --onlinedoes onegit ls-remote --tagsand reports; the session hook keeps calling the offline form. Honest, but a check nobody runs by default is close to option 1.Leaning 2, with the flag wired into a scheduled per-host job rather than into the session hook.
Also noticed
Something re-ran
install.shwith the defaultSKILLS_CHECKOUT_DIRat 14:05 today, which fast-forwarded~/.local/share/skillsand re-pointed every link there, replacing the wiring an earliertask installhad made from~/dev/skills. That is arguably correct — the default is documented as load-bearing — but it means the canonical checkout on a host can move without anyone asking for it, and~/dev/skillssilently stops being what any harness loads. Worth confirming what ran it before deciding whether it is a feature.Shipped in
b2af4e1— option 2, the opt-in flag.One
git ls-remoteagainst origin. Belongs in a scheduled per-host job, not the SessionStart hook — a check that costs latency on every session start is a check someone eventually disables.Design calls, each for a reason
Order, not equality. A host ahead of the newest tag is the normal state between a release commit and its tag landing. Same reasoning as
task check's ordering rule (#34), reusingbin/newer-version.An unreachable remote is a WARN naming itself, not a staleness FAIL. "I could not check" and "you are behind" are different answers, and collapsing them makes a network blip look like a stale library — the exact category error #38 was filed about, one level down.
The remote URL is never printed. A remote rewritten by
url.insteadOfexpands into a live token; that has leaked a credential on koala before.The default run's silence is now a test, not a comment. One of the five fixture cases stubs a newer remote tag and asserts the default invocation ignores it, so the "no network I/O" promise in doctor's header is enforced rather than trusted.
Live, on the host that motivated it
Same host, same moment: clean offline, correctly red online. That is the gap this issue described, now visible on demand.
The second observation stands unresolved
Something re-ran
install.shwith the defaultSKILLS_CHECKOUT_DIRat 14:05, which re-pointed every link from~/dev/skillsto~/.local/share/skills. Still true — the doctor output above names~/.local/share/skillsas the checkout. It is arguably correct behaviour (the default is documented as load-bearing) but it means the canonical checkout can move without anyone asking, and a~/dev/skillsyou are actively editing silently stops being what any harness loads. Worth knowing what triggered it before deciding whether that is a feature; not filed separately yet.