refactor(skills): unify installation in setup, auto-discover from disk#210
refactor(skills): unify installation in setup, auto-discover from disk#210L1nusB wants to merge 1 commit into
Conversation
|
@L1nusB is attempting to deploy a commit to the NexusCore Team on Vercel. A member of the Team first needs to authorize it. |
🟡 GitNexus Blast Radius: MEDIUM
Changed: View full blast radius graph → Generated by GitNexus — code intelligence powered by knowledge graphs |
xkonjin
left a comment
There was a problem hiding this comment.
Quick review pass:
- Main risk area here is input validation, path handling, and malformed payload behavior.
- Good to see test coverage move with the code; I’d still make sure it exercises the unhappy path around input validation, path handling, and malformed payload behavior rather than only the happy path.
- Before merge, I’d smoke-test the behavior touched by marketplace.json, SKILL.md, SKILL.md (+12 more) with malformed input / retry / rollback cases, since that’s where this class of change usually breaks.
reversTeam
left a comment
There was a problem hiding this comment.
Good refactoring work, @L1nusB. This PR cleanly separates concerns by moving skill installation out of analyze (which runs frequently) into setup (which runs once), where it belongs.
Key changes reviewed:
- ai-context.ts: Removed
installSkills()and its 6-skill hardcoded list. The__dirnamesetup is also removed since it was only needed for skill file resolution. Clean removal. - analyze.ts: New
checkStaleProjectSkills()that warns without deleting — good migration behavior. Called on both the early-return (already up to date) and full-analyze paths, so users always see the notice. - setup.ts:
discoverSkillNames()dynamically resolves skills from the filesystem instead of a hardcoded array.installSkillsTo()is now exported for testing.cleanupProjectLocalSkills()withfindRepoRoot()safely removes stale project-local skills, but only after confirming global skills installed successfully — nice guard. - README.md: Updated to reflect the new separation (analyze = index, setup = MCP + skills + hooks). Claude Code plugin section is a good addition.
- Tests: Updated
ai-context.test.tsto assert skills are NOT installed by analyze. Newanalyze-skills-notice.test.tsandsetup-skills.test.tswith good coverage of the migration path.
One observation: The marketplace.json homepage URL changed from nicosxt/gitnexus to abhigyanpatwari/GitNexus — is this an intentional ownership transfer, or was it included by mistake? Worth double-checking.
LGTM overall — solid refactor with good test coverage and a clean migration path.
f46293c to
ec5ce6b
Compare
|
Merge conflict removal |
CI Report✅ All checks passed Pipeline Status
Test Results
✅ All 4831 tests passed 46 test(s) skipped — expand for details
Code CoverageTests
📋 View full run · Generated by CI |
|
Consolidated skill installation logic into setup command and removed it from analyze. Added stale project-local skill detection and cleanup: - Remove dead installSkills function and unused imports from ai-context - Add checkStaleProjectSkills() warning in analyze after summary - Add findRepoRoot() and cleanupProjectLocalSkills() in setup - Update tests to reflect new skill installation behavior - Add analyze-skills-notice.test.ts for stale skills warnings - Fix marketplace config (name, homepage, version bump) - Update README with plugin installation note This centralizes skill lifecycle management in setup and ensures users are warned about stale project-local skills during analysis.
ec5ce6b to
240e1f3
Compare
|
Please submit a new PR if this is still relevant |
Description
Summary
analyze(was a side effect of indexing)setupthe single owner of skill installation (global only)skills/directory instead of hardcoding themProblem
When users run both
gitnexus setupandgitnexus analyze, the same skills get installed to two locations:~/.claude/skills/gitnexus-exploring/SKILL.mdsetup(global)<repo>/.claude/skills/gitnexus/gitnexus-exploring/SKILL.mdanalyze(project-local)This triggers Claude Code bug #25209 — both copies appear in the skill list instead of one shadowing the other. Users see every GitNexus skill listed twice.
Beyond the duplication bug, skills are static markdown files that don't depend on the repository index. Installing them on every
analyzerun is unnecessary work in the wrong place. There were also two separate implementations of the same install logic.Solution
Single owner:
setupinstalls skills globally to~/.claude/skills/,~/.cursor/skills/, and~/.config/opencode/skill/.analyzeno longer touches skills.Migration:
analyzeprints a deprecation notice if stale project-local skills exist.setupcleans them up after installing globally.Auto-discovery: Skill names are discovered from the
skills/source directory at install time instead of being hardcoded. This automatically picks upgitnexus-pr-review(previously missing) and prevents future breakage when skills are added or renamed.Changes
gitnexus/src/cli/ai-context.tsinstallSkills()function and its call; cleaned up unused importsgitnexus/src/cli/analyze.tscheckStaleProjectSkills()deprecation notice; updated setup tip to mention skillsgitnexus/src/cli/setup.tsdiscoverSkillNames()replacing hardcoded list; addedcleanupProjectLocalSkills()with worktree/submodule supportgitnexus/test/unit/ai-context.test.tsanalyzeno longer installs skills; regression guards for dynamic context generationgitnexus/test/unit/setup-skills.test.tsinstallSkillsTotests,setupCommandcleanup tests,discoverSkillNamesdiscovery testsgitnexus/test/unit/analyze-skills-notice.test.tscheckStaleProjectSkillsexport and behaviorREADME.mdDesign decisions
Why not keep both locations? Adds complexity to work around a bug that shouldn't exist in our code. Skills are static config — one canonical location is cleaner.
Why doesn't
analyzedelete stale skills? After the refactor,analyzeno longer owns skills. Deleting them would cross the responsibility boundary. It warns;setupcleans up.Why auto-discover instead of hardcode? The hardcoded
SKILL_NAMESlist was the root cause ofgitnexus-pr-reviewbeing silently excluded. Discovery from disk means adding a new skill is just dropping a file — no code change required.Worktree/submodule support:
cleanupProjectLocalSkillswalks upward to find the repo root, handling.gitas either a directory (standard) or a file (worktrees/submodules).Test plan
analyzeno longer creates.claude/skills/gitnexus/(acceptance tests 1-2)analyzeprints deprecation notice when stale skills exist (15-17)analyzeshows notice even on "Already up to date" early returnsetupinstalls all 7 discovered skills with non-empty SKILL.md (7-9)setupremoves project-local skills in git repos (11-12)setuphandles nested dirs, worktrees, non-git dirs, empty dirs (13-14, nested/worktree tests)discoverSkillNamesdiscovers flat files, directories, mixed layouts (27-33)discoverSkillNamesfilters togitnexus-*prefix only (28)discoverSkillNamesignores directories without SKILL.md (33)discoverSkillNamesdocuments collision behavior for same-name flat+directory entries (34)discoverSkillNamespropagates errors: missing root (ENOENT), permission failure (EACCES) (35-36)SKILL_NAMESlazy-population contract: starts empty, populated after first install (37)