Class: BundlerSkills::Synchronizer

Inherits:
Object
  • Object
show all
Defined in:
lib/bundler_skills/synchronizer.rb

Overview

Orchestrates discovery -> linking across the resolved agents. Shared entry point for both the Hook (after-install-all) and the manual ‘bundle skills` command.

Discovery runs once (agent-independent); linking runs once per distinct output directory (.claude/skills and/or .agents/skills). Phase 4 adds the .gitignore update.

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Constructor Details

#initialize(root: Bundler.root, config: Config.load, logger: Bundler.ui, specs: nil) ⇒ Synchronizer

Returns a new instance of Synchronizer.



14
15
16
17
18
19
# File 'lib/bundler_skills/synchronizer.rb', line 14

def initialize(root: Bundler.root, config: Config.load, logger: Bundler.ui, specs: nil)
  @root = root
  @config = config
  @logger = logger
  @specs = specs
end

Instance Method Details

#cleanObject

Remove every gem- symlink we own across all known output dirs. Used by ‘bundle skills clean`. Returns { subdir => [removed names] }.



83
84
85
86
87
88
89
# File 'lib/bundler_skills/synchronizer.rb', line 83

def clean
  AgentRegistry.all.map(&:skills_subdir).uniq.to_h do |subdir|
    skills_dir = File.join(@root.to_s, subdir)
    linker = Linker.new(skills_dir: skills_dir, config: @config, logger: @logger)
    [subdir, linker.clean_all]
  end
end

#planObject

Discover skills and the agents/dirs that would receive them, without touching the filesystem. Used by ‘bundle skills list`.



72
73
74
75
76
77
78
79
# File 'lib/bundler_skills/synchronizer.rb', line 72

def plan
  skills = Discoverer.new(specs: @specs, config: @config, logger: @logger).discover
  agents = AgentRegistry.resolve(@root, @config)
  Result.new(
    discovered: skills, agents: agents,
    links_by_dir: {}, gitignore_changed: false
  )
end

#syncObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/bundler_skills/synchronizer.rb', line 21

def sync
  skills = Discoverer.new(specs: @specs, config: @config, logger: @logger).discover
  agents = AgentRegistry.resolve(@root, @config)
  subdirs = AgentRegistry.output_subdirs(agents)

  links_by_dir = subdirs.to_h do |subdir|
    skills_dir = File.join(@root.to_s, subdir)
    linker = Linker.new(skills_dir: skills_dir, config: @config, logger: @logger)
    [subdir, linker.link(skills, prune_scope: :all)]
  end

  gitignore_changed = update_gitignore(subdirs)

  log_summary(skills, agents, links_by_dir)
  Result.new(
    discovered: skills, agents: agents,
    links_by_dir: links_by_dir, gitignore_changed: gitignore_changed
  )
end

#sync_gem(spec) ⇒ Object

Sync the skills of a SINGLE gem (used by the RubyGems post_install hook).

Only links belonging to this gem (gem-<name>–*) are added/updated, and only this gem’s stale links are pruned — every other gem’s links are left untouched. So when a gem’s new version drops or renames a skill, its old link is removed, but unrelated gems are never disturbed.

Parameters:

  • spec (#name, #full_gem_path)

    a Gem::Specification (or compatible)



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/bundler_skills/synchronizer.rb', line 49

def sync_gem(spec)
  skills = Discoverer.new(specs: [spec], config: @config, logger: @logger).discover
  agents = AgentRegistry.resolve(@root, @config)
  subdirs = AgentRegistry.output_subdirs(agents)
  scope = ["#{DiscoveredSkill::LINK_PREFIX}#{spec.name}#{DiscoveredSkill::BOUNDARY}"]

  links_by_dir = subdirs.to_h do |subdir|
    skills_dir = File.join(@root.to_s, subdir)
    linker = Linker.new(skills_dir: skills_dir, config: @config, logger: @logger)
    [subdir, linker.link(skills, prune_scope: scope)]
  end

  gitignore_changed = update_gitignore(subdirs)

  log_summary(skills, agents, links_by_dir)
  Result.new(
    discovered: skills, agents: agents,
    links_by_dir: links_by_dir, gitignore_changed: gitignore_changed
  )
end