Keep the agent skill fresh across upgrades and script-drive Homebrew updates#57
Conversation
…pdates Skill freshness: - Copy-mode skill syncs write a .smith-skill-meta.json marker recording the source and smith version, so smith-managed copies are distinguishable from hand-rolled directories. - ensure_skill_fresh() runs on CLI startup (throttled to once per day, SMITH_SKILL_CHECK=0 kill switch) and silently re-syncs stale marker-bearing copies and broken symlinks. Unmanaged directories only get a stderr hint; working symlinks are never touched. - sync_skill swaps in the new skill via a staged copy so a mid-copy failure restores the previous install instead of leaving a partial one. - scripts/install.py delegates to smith skill sync (locating fresh installs via uv tool dir --bin), keeping its copy logic only as a PATH fallback. Homebrew release plumbing: - update_homebrew_formula.py owns the canonical bootstrap build-backend list (--print-extra-packages, --sync-bootstrap-resources with resource-stanza validation) and can pin GitHub release tarballs via --sha256, parsing both the old git pin and the new tarball pin. - The release validation workflow now dispatches the tap's Update Smith Formula workflow with HOMEBREW_TAP_DISPATCH_TOKEN, falling back to the manual handoff message when the secret is absent. Bump version to 0.1.3 to carry the script flags the tap workflow needs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Lines 205 to 207 in e094dc0
When the target is an unmarked copied directory whose contents already match the source (for example a copy produced by an older installer or the fallback path), this early current return skips writing .smith-skill-meta.json. On a later upgrade, ensure_skill_fresh sees the now-stale directory but refuses to refresh it because marker is None, so even a user who ran smith skill sync while it was current will only get the manual hint instead of automatic refresh. For directory-mode current targets, backfill the marker before returning.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| found = shutil.which("smith") | ||
| if found: | ||
| return found |
There was a problem hiding this comment.
Prefer the freshly installed uv tool over PATH
When a user already has an older smith earlier on PATH (for example from Homebrew or a prior uv/pipx install), this returns that stale executable instead of the uv tool install result. The subsequent smith skill sync can therefore run the old sync implementation; in particular pre-marker versions sync successfully but do not write .smith-skill-meta.json, so the installer's copy is not recognized as smith-managed and will not auto-refresh on later upgrades. Since the script has just installed the intended CLI, it should locate/use uv's tool bin before falling back to PATH.
Useful? React with 👍 / 👎.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
Skill freshness (auto-update on
brew upgrade):.smith-skill-meta.jsonmarker (source path + smith version) so smith-managed copies are distinguishable from hand-rolled directories.ensure_skill_fresh()runs on CLI startup, throttled to once/24h (SMITH_SKILL_CHECK=0kill switch). It silently re-syncs stale marker-bearing copies and repairs broken symlinks, printing one stderr line. Unmanaged directories only get a hint — smith never deletes content it didn't write. Working symlinks are never touched (they already track upgrades via Homebrew'soptpath, and devs deliberately link repo checkouts).sync_skillnow swaps via a staged copy: a mid-copy failure restores the previous install instead of leaving a partial one.scripts/install.pydelegates tosmith skill sync(locating fresh installs viauv tool dir --bin), so all install paths share one sync implementation.Homebrew release plumbing:
update_homebrew_formula.pyowns the canonical bootstrap build-backend list (--print-extra-packages,--sync-bootstrap-resourceswith resource-stanza validation) and pins GitHub release tarballs via--sha256, parsing both the old git pin and new tarball pin forms.HOMEBREW_TAP_DISPATCH_TOKEN(fine-grained PAT, Actions r/w on the tap only — no contents write), falling back to the manual-handoff message when the secret is absent.workflow-script-driven-update).Test plan
make checkpasses (lint, format, mypy, 790+ unit/contract tests with coverage gates, skill validation).ruby -cclean).