post-push hook never ran: git has no such hook, so no plugin cache was refreshed #78
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
scripts/git-hooks/post-pushonly runsclaude plugin update kyberforgeafter a push. It doesn't update thegiteaplugin.Found while closing out #67 (the gitea deep-modules refactor): after merging that PR, the installed cache at
~/.claude/plugins/cache/holocron/gitea/was still pinned at1.0.0— the pre-refactor version with noskills/directory at all. None of the new skills (gitea-issues,gitea-prs,gitea-workflow, etc.) were available in the session until manually refreshed, because the hook that's supposed to keep plugin caches current silently skips this plugin.Impact
Any session (this machine or another) that pushes to
maingets itskyberforgecache refreshed automatically but notgitea— changes to gitea skills/agents merged to main don't take effect until someone notices and runsclaude plugin update giteaby hand. This already caused a stale-skill situation immediately after #67 merged.Fix
Update
scripts/git-hooks/post-pushto updategiteaalongside (or instead of hardcodingkyberforge, e.g. iterate all installed plugins tracked by the holocron marketplace, or accept a list). Should probably also coverbin,core,gitfor the same reason unless there's a reasonkyberforgewas special-cased.The premise here is wrong, and in a more interesting way than "outdated"
This issue says the hook refreshes
kyberforgeautomatically but skipsgitea. It skips everything: git has no client-sidepost-pushhook. It is not ingithooks(5)and git 2.39.5 never invokes one.scripts/install.shcopies every file inscripts/git-hooks/into.git/hooks/, so.git/hooks/post-pushexisted on disk and looked installed. It had never fired once, from the day it was added. The stalegiteacache after #67 was not a special case — it was the only observable symptom of a mechanism that had never worked at all.Two tests appeared to cover it and did not:
tests/test-post-push.shinvoked the script directly with mockedgit/claudeand asserted its behaviour.tests/test-git-hooks-install.shasserted only that install.sh copied the file into.git/hooks/.Neither asserted that git ever runs it. That gap is why this sat undetected for six weeks.
The fix is not the one proposed here
This issue proposes iterating all installed plugins instead of hardcoding
kyberforge. That would have produced a correct list inside a script that still never executes.Refreshing on push is also the wrong trigger regardless of hook mechanics: your install goes stale when someone else merges, so a push of your own is neither necessary nor sufficient for staleness to have occurred.
claude plugin updateis moot besides — ADR-0018 moved this repo to consuming its own packages through apm, so there is no plugin cache to refresh.What replaces it
ADR-0019. kyberforge ships a
SessionStarthook that runsapm outdatedand, when anything is behind, runsapm update --yesand returnsreloadSkills: trueso the running session picks up the redeployed content.SessionStartis the right trigger because the thing that goes stale is the skill content a session loads, and it can do two things a git hook structurally cannot: put the notice into the agent's context, and reload skills without a restart.Measured: ~0.7 s when current, ~10.4 s when six packages are behind and the refresh runs.
scripts/git-hooks/post-pushandtests/test-post-push.share deleted.install.sh's copy block is generic and kept, withtest-git-hooks-install.shnow synthesizing its own fixture hook so the mechanism stays tested without a dead hook to prop it up.Two related findings from the same work, both verified rather than assumed:
${CLAUDE_PLUGIN_ROOT}against the installed package root, andapm packkeeps only*.jsonout of.apm/hooks/— so a.../hooks/<script>reference points into the generated mirror where the script does not exist. apm printsHook script not foundand deploys a hook aimed at nothing. A test now pins the.apm/-relative form.apm approve --listreportsExecutable-trust gate disabled -- all executables deployuntil anexecutables:block exists inapm.yml. Every hook, bin, and MCP primitive a dependency shipped would have deployed unprompted. Now enabled for this repo.Closed by PR #98.
post-push hook doesn't refresh the gitea plugin cacheto post-push hook never ran: git has no such hook, so no plugin cache was refreshed