Module: Ace::Sim

Defined in:
lib/ace/sim.rb,
lib/ace/sim/cli.rb,
lib/ace/sim/version.rb,
lib/ace/sim/cli/commands/run.rb,
lib/ace/sim/molecules/session_store.rb,
lib/ace/sim/molecules/source_bundler.rb,
lib/ace/sim/molecules/stage_executor.rb,
lib/ace/sim/models/simulation_session.rb,
lib/ace/sim/molecules/synthesis_builder.rb,
lib/ace/sim/organisms/simulation_runner.rb,
lib/ace/sim/molecules/final_synthesis_executor.rb

Defined Under Namespace

Modules: CLI, Models, Molecules, Organisms Classes: Error, ValidationError

Constant Summary collapse

VERSION =
'0.15.4'

Class Method Summary collapse

Class Method Details

.configObject



30
31
32
33
34
35
36
# File 'lib/ace/sim.rb', line 30

def config
  @config ||= begin
    defaults = load_defaults
    user_config = config_resolver.resolve_namespace("sim").to_h
    Ace::Support::Config::Models::Config.wrap(defaults, user_config, source: "sim")
  end
end

.config_resolverObject



120
121
122
# File 'lib/ace/sim.rb', line 120

def config_resolver
  @config_resolver ||= Ace::Support::Config.create(gem_path: gem_root)
end

.default_preset_nameObject



104
105
106
# File 'lib/ace/sim.rb', line 104

def default_preset_name
  get("sim", "default_preset") || "validate-idea"
end

.gem_rootObject



124
125
126
# File 'lib/ace/sim.rb', line 124

def gem_root
  Gem.loaded_specs["ace-sim"]&.gem_dir || File.expand_path("../..", __dir__)
end

.get(*keys) ⇒ Object



38
39
40
# File 'lib/ace/sim.rb', line 38

def get(*keys)
  config.dig(*keys)
end

.load_preset(name) ⇒ Object

Raises:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/ace/sim.rb', line 65

def load_preset(name)
  preset_name = name.to_s.strip
  return nil if preset_name.empty?

  data = config_resolver.resolve_file([
    "sim/presets/#{preset_name}.yml",
    "sim/presets/#{preset_name}.yaml"
  ]).data

  preset = if data.nil? || data.empty?
    return nil unless preset_names.include?(preset_name)

    {"steps" => normalize_list(get("sim", "default_steps"))}
  else
    data["preset"] || data
  end

  steps = normalize_list(preset["steps"])
  raise ValidationError, "Preset '#{preset_name}' has no steps" if steps.empty?

  normalized = preset.to_h.each_with_object({}) { |(k, v), acc| acc[k.to_s] = v }
  normalized["name"] = preset_name
  normalized["steps"] = steps
  normalized
end

.next_run_idObject



108
109
110
111
112
113
# File 'lib/ace/sim.rb', line 108

def next_run_id
  timestamp = Time.now.utc.to_i.to_s(36)
  "#{Ace::B36ts.now}-#{timestamp}-#{random_run_suffix}"
rescue
  "#{Time.now.utc.to_i.to_s(36)}-#{random_run_suffix}"
end

.normalize_list(raw) ⇒ Object



26
27
28
# File 'lib/ace/sim.rb', line 26

def normalize_list(raw)
  Array(raw).flatten.compact.map(&:to_s).map(&:strip).reject(&:empty?)
end

.preset_namesObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/ace/sim.rb', line 48

def preset_names
  @preset_names ||= begin
    dirs = [
      File.join(gem_root, ".ace-defaults", "sim", "presets"),
      File.join(Dir.home, ".ace", "sim", "presets"),
      File.join(Dir.pwd, ".ace", "sim", "presets")
    ]

    dirs.filter_map do |dir|
      next unless Dir.exist?(dir)

      files = Dir.glob(File.join(dir, "*.yml")) + Dir.glob(File.join(dir, "*.yaml"))
      files.map { |path| File.basename(path, ".*") }
    end.flatten.uniq.sort
  end
end

.reset_config!Object



42
43
44
45
46
# File 'lib/ace/sim.rb', line 42

def reset_config!
  @config = nil
  @config_resolver = nil
  @preset_names = nil
end

.step_bundle_path(step) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/ace/sim.rb', line 91

def step_bundle_path(step)
  step_name = step.to_s.strip
  return nil if step_name.empty?

  candidates = [
    File.join(Dir.pwd, ".ace", "sim", "steps", "#{step_name}.md"),
    File.join(Dir.home, ".ace", "sim", "steps", "#{step_name}.md"),
    File.join(gem_root, ".ace-defaults", "sim", "steps", "#{step_name}.md")
  ]

  candidates.find { |path| File.exist?(path) }
end