ukiryu 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release.yml +58 -14
  3. data/.gitignore +3 -0
  4. data/.rubocop_todo.yml +170 -79
  5. data/Gemfile +1 -1
  6. data/README.adoc +1603 -576
  7. data/docs/.gitignore +1 -0
  8. data/docs/Gemfile +10 -0
  9. data/docs/INDEX.adoc +261 -0
  10. data/docs/_config.yml +180 -0
  11. data/docs/advanced/custom-tool-classes.adoc +581 -0
  12. data/docs/advanced/index.adoc +20 -0
  13. data/docs/features/configuration.adoc +657 -0
  14. data/docs/features/index.adoc +31 -0
  15. data/docs/features/platform-support.adoc +488 -0
  16. data/docs/getting-started/core-concepts.adoc +666 -0
  17. data/docs/getting-started/index.adoc +36 -0
  18. data/docs/getting-started/installation.adoc +216 -0
  19. data/docs/getting-started/quick-start.adoc +258 -0
  20. data/docs/guides/env-var-sets.adoc +388 -0
  21. data/docs/guides/index.adoc +20 -0
  22. data/docs/interfaces/cli.adoc +609 -0
  23. data/docs/interfaces/index.adoc +153 -0
  24. data/docs/interfaces/ruby-api.adoc +538 -0
  25. data/docs/lychee.toml +49 -0
  26. data/docs/reference/configuration-options.adoc +720 -0
  27. data/docs/reference/error-codes.adoc +634 -0
  28. data/docs/reference/index.adoc +20 -0
  29. data/docs/reference/ruby-api.adoc +1217 -0
  30. data/docs/understanding/index.adoc +20 -0
  31. data/lib/ukiryu/cli.rb +43 -58
  32. data/lib/ukiryu/cli_commands/base_command.rb +16 -27
  33. data/lib/ukiryu/cli_commands/cache_command.rb +100 -0
  34. data/lib/ukiryu/cli_commands/commands_command.rb +8 -8
  35. data/lib/ukiryu/cli_commands/commands_command.rb.fixed +1 -1
  36. data/lib/ukiryu/cli_commands/config_command.rb +49 -7
  37. data/lib/ukiryu/cli_commands/definitions_command.rb +254 -0
  38. data/lib/ukiryu/cli_commands/describe_command.rb +13 -7
  39. data/lib/ukiryu/cli_commands/describe_command.rb.fixed +1 -1
  40. data/lib/ukiryu/cli_commands/docs_command.rb +148 -0
  41. data/lib/ukiryu/cli_commands/exec_inline_command.rb.fixed +1 -1
  42. data/lib/ukiryu/cli_commands/extract_command.rb +2 -2
  43. data/lib/ukiryu/cli_commands/info_command.rb +7 -7
  44. data/lib/ukiryu/cli_commands/lint_command.rb +167 -0
  45. data/lib/ukiryu/cli_commands/list_command.rb +6 -6
  46. data/lib/ukiryu/cli_commands/opts_command.rb +2 -2
  47. data/lib/ukiryu/cli_commands/opts_command.rb.fixed +1 -1
  48. data/lib/ukiryu/cli_commands/register_command.rb +144 -0
  49. data/lib/ukiryu/cli_commands/resolve_command.rb +124 -0
  50. data/lib/ukiryu/cli_commands/run_command.rb +38 -14
  51. data/lib/ukiryu/cli_commands/run_file_command.rb +2 -2
  52. data/lib/ukiryu/cli_commands/system_command.rb +50 -32
  53. data/lib/ukiryu/cli_commands/validate_command.rb +452 -51
  54. data/lib/ukiryu/cli_commands/which_command.rb +5 -5
  55. data/lib/ukiryu/command_builder.rb +81 -23
  56. data/lib/ukiryu/config/env_provider.rb +3 -3
  57. data/lib/ukiryu/config/env_schema.rb +6 -6
  58. data/lib/ukiryu/config.rb +11 -11
  59. data/lib/ukiryu/definition/definition_cache.rb +238 -0
  60. data/lib/ukiryu/definition/definition_composer.rb +257 -0
  61. data/lib/ukiryu/definition/definition_linter.rb +460 -0
  62. data/lib/ukiryu/definition/definition_validator.rb +320 -0
  63. data/lib/ukiryu/definition/discovery.rb +239 -0
  64. data/lib/ukiryu/definition/documentation_generator.rb +429 -0
  65. data/lib/ukiryu/definition/lint_issue.rb +168 -0
  66. data/lib/ukiryu/definition/loader.rb +139 -0
  67. data/lib/ukiryu/definition/metadata.rb +159 -0
  68. data/lib/ukiryu/definition/source.rb +87 -0
  69. data/lib/ukiryu/definition/sources/file.rb +138 -0
  70. data/lib/ukiryu/definition/sources/string.rb +88 -0
  71. data/lib/ukiryu/definition/validation_result.rb +158 -0
  72. data/lib/ukiryu/definition/version_resolver.rb +194 -0
  73. data/lib/ukiryu/definition.rb +40 -0
  74. data/lib/ukiryu/errors.rb +6 -0
  75. data/lib/ukiryu/execution_context.rb +11 -11
  76. data/lib/ukiryu/executor.rb +6 -0
  77. data/lib/ukiryu/extractors/extractor.rb +6 -5
  78. data/lib/ukiryu/extractors/help_parser.rb +13 -19
  79. data/lib/ukiryu/logger.rb +3 -1
  80. data/lib/ukiryu/models/command_definition.rb +3 -3
  81. data/lib/ukiryu/models/command_info.rb +1 -1
  82. data/lib/ukiryu/models/components.rb +1 -3
  83. data/lib/ukiryu/models/env_var_definition.rb +11 -3
  84. data/lib/ukiryu/models/flag_definition.rb +15 -0
  85. data/lib/ukiryu/models/option_definition.rb +7 -7
  86. data/lib/ukiryu/models/platform_profile.rb +6 -3
  87. data/lib/ukiryu/models/routing.rb +1 -1
  88. data/lib/ukiryu/models/tool_definition.rb +2 -4
  89. data/lib/ukiryu/models/tool_metadata.rb +6 -6
  90. data/lib/ukiryu/models/validation_result.rb +1 -1
  91. data/lib/ukiryu/models/version_compatibility.rb +6 -3
  92. data/lib/ukiryu/models/version_detection.rb +10 -1
  93. data/lib/ukiryu/{registry.rb → register.rb} +54 -38
  94. data/lib/ukiryu/register_auto_manager.rb +268 -0
  95. data/lib/ukiryu/schema_validator.rb +31 -10
  96. data/lib/ukiryu/shell/base.rb +18 -0
  97. data/lib/ukiryu/shell/bash.rb +19 -1
  98. data/lib/ukiryu/shell/cmd.rb +11 -1
  99. data/lib/ukiryu/shell/powershell.rb +11 -1
  100. data/lib/ukiryu/shell.rb +1 -1
  101. data/lib/ukiryu/tool.rb +107 -95
  102. data/lib/ukiryu/tool_index.rb +22 -22
  103. data/lib/ukiryu/tools/base.rb +12 -25
  104. data/lib/ukiryu/tools/generator.rb +7 -7
  105. data/lib/ukiryu/tools.rb +3 -3
  106. data/lib/ukiryu/type.rb +20 -5
  107. data/lib/ukiryu/version.rb +1 -1
  108. data/lib/ukiryu/version_detector.rb +21 -2
  109. data/lib/ukiryu.rb +6 -3
  110. data/ukiryu-proposal.md +41 -41
  111. data/ukiryu.gemspec +1 -0
  112. metadata +64 -8
  113. data/.gitmodules +0 -3
@@ -9,21 +9,29 @@ module Ukiryu
9
9
  # @example
10
10
  # env_var = EnvVarDefinition.new(
11
11
  # name: 'DISPLAY',
12
- # env_var: 'DISPLAY',
13
12
  # value: '',
14
13
  # platforms: [:linux, :macos]
15
14
  # )
16
15
  class EnvVarDefinition < Lutaml::Model::Serializable
17
16
  attribute :name, :string
18
- attribute :env_var, :string
19
17
  attribute :value, :string
18
+ attribute :from, :string
20
19
  attribute :platforms, :string, collection: true, default: []
20
+ attribute :description, :string
21
21
 
22
22
  yaml do
23
23
  map_element 'name', to: :name
24
- map_element 'env_var', to: :env_var
25
24
  map_element 'value', to: :value
25
+ map_element 'from', to: :from
26
26
  map_element 'platforms', to: :platforms
27
+ map_element 'description', to: :description
28
+ end
29
+
30
+ # Get platforms as symbol array
31
+ #
32
+ # @return [Array<Symbol>] platforms as symbols
33
+ def platforms_sym
34
+ @platforms_sym ||= platforms&.map(&:to_sym) || []
27
35
  end
28
36
  end
29
37
  end
@@ -18,16 +18,24 @@ module Ukiryu
18
18
  class FlagDefinition < Lutaml::Model::Serializable
19
19
  attribute :name, :string
20
20
  attribute :cli, :string
21
+ attribute :cli_short, :string
21
22
  attribute :default, :boolean, default: false
22
23
  attribute :description, :string
23
24
  attribute :platforms, :string, collection: true, default: []
25
+ attribute :position_constraint, :string
26
+ attribute :position_after, :string
27
+ attribute :conflicts_with, :string, collection: true, default: []
24
28
 
25
29
  yaml do
26
30
  map_element 'name', to: :name
27
31
  map_element 'cli', to: :cli
32
+ map_element 'cli_short', to: :cli_short
28
33
  map_element 'default', to: :default
29
34
  map_element 'description', to: :description
30
35
  map_element 'platforms', to: :platforms
36
+ map_element 'position_constraint', to: :position_constraint
37
+ map_element 'position_after', to: :position_after
38
+ map_element 'conflicts_with', to: :conflicts_with
31
39
  end
32
40
 
33
41
  # Get the effective default value
@@ -54,6 +62,13 @@ module Ukiryu
54
62
  @name_sym ||= name.to_sym
55
63
  end
56
64
 
65
+ # Get position_constraint as symbol (cached)
66
+ #
67
+ # @return [Symbol, nil] the position constraint as symbol, or nil if not set
68
+ def position_constraint_sym
69
+ @position_constraint_sym ||= position_constraint&.to_sym
70
+ end
71
+
57
72
  private
58
73
 
59
74
  # Get platforms as cached symbol array
@@ -13,14 +13,14 @@ module Ukiryu
13
13
  # name: 'quality',
14
14
  # cli: '-q',
15
15
  # type: 'integer',
16
- # format: 'single_dash_space',
16
+ # assignment_delimiter: 'space',
17
17
  # description: 'JPEG quality'
18
18
  # )
19
19
  class OptionDefinition < Lutaml::Model::Serializable
20
20
  attribute :name, :string
21
21
  attribute :cli, :string
22
22
  attribute :type, :string, default: 'string'
23
- attribute :format, :string, default: 'single_dash_space'
23
+ attribute :assignment_delimiter, :string, default: 'auto'
24
24
  attribute :separator, :string
25
25
  attribute :default, :string
26
26
  # Array for numeric range [min, max]
@@ -36,7 +36,7 @@ module Ukiryu
36
36
  map_element 'name', to: :name
37
37
  map_element 'cli', to: :cli
38
38
  map_element 'type', to: :type
39
- map_element 'format', to: :format
39
+ map_element 'assignment_delimiter', to: :assignment_delimiter
40
40
  map_element 'separator', to: :separator
41
41
  map_element 'default', to: :default
42
42
  map_element 'range', to: :range
@@ -63,11 +63,11 @@ module Ukiryu
63
63
  type == 'boolean'
64
64
  end
65
65
 
66
- # Get format as symbol (cached for performance)
66
+ # Get assignment delimiter as symbol
67
67
  #
68
- # @return [Symbol] the format
69
- def format_sym
70
- @format_sym ||= format&.to_sym || :single_dash_space
68
+ # @return [Symbol] the assignment delimiter
69
+ def assignment_delimiter_sym
70
+ @assignment_delimiter_sym ||= assignment_delimiter.to_sym
71
71
  end
72
72
 
73
73
  # Hash-like access for Type validation compatibility
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'lutaml/model'
4
4
  require_relative 'command_definition'
5
+ require_relative 'env_var_definition'
5
6
  require_relative 'routing'
6
7
  require_relative 'exit_codes'
7
8
 
@@ -23,9 +24,10 @@ module Ukiryu
23
24
  attribute :option_style, :string, default: 'single_dash_space'
24
25
  attribute :commands, CommandDefinition, collection: true, initialize_empty: true
25
26
  attribute :inherits, :string
26
- attribute :routing_data, :hash, default: {} # Raw routing from YAML
27
- attribute :version_requirement, :string # Semantic version requirement (e.g., ">= 2.30")
28
- attribute :exit_codes, ExitCodes # Exit code definitions for this profile
27
+ attribute :routing_data, :hash, default: {} # Raw routing from YAML
28
+ attribute :version_requirement, :string # Semantic version requirement (e.g., ">= 2.30")
29
+ attribute :exit_codes, ExitCodes # Exit code definitions for this profile
30
+ attribute :env_var_sets, :hash, default: {} # Reusable env var sets (e.g., "headless")
29
31
 
30
32
  yaml do
31
33
  map_element 'name', to: :name
@@ -38,6 +40,7 @@ module Ukiryu
38
40
  map_element 'routing', to: :routing_data
39
41
  map_element 'version_requirement', to: :version_requirement
40
42
  map_element 'exit_codes', to: :exit_codes
43
+ map_element 'env_var_sets', to: :env_var_sets
41
44
  end
42
45
 
43
46
  # Get the routing table as a Routing model
@@ -191,7 +191,7 @@ module Ukiryu
191
191
  # @return [String] routing table as formatted string
192
192
  #
193
193
  def to_s
194
- return "(empty)" if @table.empty?
194
+ return '(empty)' if @table.empty?
195
195
 
196
196
  @table.map { |k, v| "#{k} => #{v}" }.join(', ')
197
197
  end
@@ -26,7 +26,7 @@ module Ukiryu
26
26
  attribute :profiles, PlatformProfile, collection: true
27
27
  attribute :version_detection, VersionDetection
28
28
  attribute :search_paths, SearchPaths
29
- attribute :components, Components # Registry of reusable definitions
29
+ attribute :components, Components # Register of reusable definitions
30
30
 
31
31
  yaml do
32
32
  map_element 'ukiryu_schema', to: :ukiryu_schema
@@ -129,9 +129,7 @@ module Ukiryu
129
129
  # Get the self URI
130
130
  #
131
131
  # @return [String, nil] the self URI
132
- def self_uri
133
- @self_uri
134
- end
132
+ attr_reader :self_uri
135
133
 
136
134
  # Check if a specific schema version is specified
137
135
  #
@@ -9,11 +9,11 @@ module Ukiryu
9
9
  # without loading the full profile definition
10
10
 
11
11
  attr_reader :name, :version, :display_name, :implements, :homepage,
12
- :description, :aliases, :tool_name, :registry_path, :default_command
12
+ :description, :aliases, :tool_name, :register_path, :default_command
13
13
 
14
14
  def initialize(name:, version:, display_name: nil, implements: nil,
15
15
  homepage: nil, description: nil, aliases: nil,
16
- tool_name: nil, registry_path: nil, default_command: nil)
16
+ tool_name: nil, register_path: nil, default_command: nil)
17
17
  @name = name
18
18
  @version = version
19
19
  @display_name = display_name
@@ -22,7 +22,7 @@ module Ukiryu
22
22
  @description = description
23
23
  @aliases = Array(aliases || [])
24
24
  @tool_name = tool_name || name
25
- @registry_path = registry_path
25
+ @register_path = register_path
26
26
  @default_command = default_command
27
27
  end
28
28
 
@@ -62,9 +62,9 @@ module Ukiryu
62
62
  #
63
63
  # @param hash [Hash] the YAML profile hash
64
64
  # @param tool_name [String] the tool name
65
- # @param registry_path [String] the registry path
65
+ # @param register_path [String] the register path
66
66
  # @return [ToolMetadata] the metadata object
67
- def self.from_hash(hash, tool_name:, registry_path: nil)
67
+ def self.from_hash(hash, tool_name:, register_path: nil)
68
68
  new(
69
69
  name: tool_name,
70
70
  version: hash['version'],
@@ -75,7 +75,7 @@ module Ukiryu
75
75
  aliases: hash['aliases'],
76
76
  default_command: hash['default_command'],
77
77
  tool_name: tool_name,
78
- registry_path: registry_path
78
+ register_path: register_path
79
79
  )
80
80
  end
81
81
  end
@@ -49,7 +49,7 @@ module Ukiryu
49
49
  # @return [String] status message
50
50
  def status_message
51
51
  if valid?
52
- "✓ Valid"
52
+ '✓ Valid'
53
53
  else
54
54
  "✗ Invalid (#{errors.size} error#{errors.size == 1 ? '' : 's'})"
55
55
  end
@@ -52,7 +52,10 @@ module Ukiryu
52
52
  # @param requirement [String] the version requirement (e.g., ">= 2.30")
53
53
  # @return [VersionCompatibility] the compatibility result
54
54
  def self.check(installed_version, requirement)
55
- return new(installed_version: installed_version, required_version: requirement, compatible: true, reason: nil) if !requirement || requirement.empty?
55
+ if !requirement || requirement.empty?
56
+ return new(installed_version: installed_version, required_version: requirement, compatible: true,
57
+ reason: nil)
58
+ end
56
59
 
57
60
  parser = RequirementParser.new(requirement)
58
61
  compatible = parser.satisfied_by?(installed_version)
@@ -112,9 +115,9 @@ module Ukiryu
112
115
 
113
116
  case constraint[:operator]
114
117
  when '>', '>='
115
- compare_versions(v, req_v) > 0 || (constraint[:operator] == '>=' && v == req_v)
118
+ compare_versions(v, req_v).positive? || (constraint[:operator] == '>=' && v == req_v)
116
119
  when '<', '<='
117
- compare_versions(v, req_v) < 0 || (constraint[:operator] == '<=' && v == req_v)
120
+ compare_versions(v, req_v).negative? || (constraint[:operator] == '<=' && v == req_v)
118
121
  when '==', '='
119
122
  v == req_v
120
123
  when '!='
@@ -6,21 +6,30 @@ module Ukiryu
6
6
  module Models
7
7
  # Version detection configuration
8
8
  #
9
- # @example
9
+ # @example Command-based version detection (GNU tools)
10
10
  # vd = VersionDetection.new(
11
11
  # command: '--version',
12
12
  # pattern: '(\d+\.\d+)',
13
13
  # modern_threshold: '7.0'
14
14
  # )
15
+ #
16
+ # @example Man-page based version detection (BSD/system tools)
17
+ # vd = VersionDetection.new(
18
+ # command: ['man', 'find'],
19
+ # pattern: 'macOS ([\d.]+)',
20
+ # source: 'man'
21
+ # )
15
22
  class VersionDetection < Lutaml::Model::Serializable
16
23
  attribute :command, :string, collection: true, default: []
17
24
  attribute :pattern, :string
18
25
  attribute :modern_threshold, :string
26
+ attribute :source, :string, default: 'command' # 'command' or 'man'
19
27
 
20
28
  yaml do
21
29
  map_element 'command', to: :command
22
30
  map_element 'pattern', to: :pattern
23
31
  map_element 'modern_threshold', to: :modern_threshold
32
+ map_element 'source', to: :source
24
33
  end
25
34
 
26
35
  # Hash-like access for Base.detect_version compatibility
@@ -5,41 +5,43 @@ require_relative 'models/tool_metadata'
5
5
  require_relative 'models/validation_result'
6
6
  require_relative 'tool_index'
7
7
  require_relative 'schema_validator'
8
+ require_relative 'register_auto_manager'
8
9
 
9
10
  module Ukiryu
10
- # YAML profile registry loader
11
+ # YAML profile register loader
11
12
  #
12
- # Provides access to tool definitions from YAML profiles in a registry directory.
13
+ # Provides access to tool definitions from YAML profiles in a register directory.
13
14
  # Supports lazy loading: metadata can be loaded without full profile parsing.
14
15
  #
15
16
  # Features:
16
17
  # - Cached version listings to avoid repeated glob operations
17
- # - Automatic cache invalidation when registry path changes
18
- class Registry
18
+ # - Automatic cache invalidation when register path changes
19
+ # - Automatic register cloning to ~/.ukiryu/register if not configured
20
+ class Register
19
21
  class << self
20
- # Set the default registry path
22
+ # Set the default register path
21
23
  #
22
- # @param path [String] the default registry path
24
+ # @param path [String] the default register path
23
25
 
24
- # Get the default registry path
26
+ # Get the default register path
25
27
  #
26
- # @return [String, nil] the default registry path
27
- attr_accessor :default_registry_path
28
+ # @return [String, nil] the default register path
29
+ attr_accessor :default_register_path
28
30
 
29
31
  # Reset the version cache (mainly for testing)
30
32
  def reset_version_cache
31
33
  @version_cache = nil
32
- @registry_cache_key = nil
34
+ @register_cache_key = nil
33
35
  end
34
36
 
35
37
  # Get all available tool names
36
38
  #
37
39
  # @return [Array<String>] list of tool names
38
40
  def tools
39
- registry_path = @default_registry_path
40
- return [] unless registry_path
41
+ register_path = effective_register_path
42
+ return [] unless register_path
41
43
 
42
- tools_dir = File.join(registry_path, 'tools')
44
+ tools_dir = File.join(register_path, 'tools')
43
45
  return [] unless Dir.exist?(tools_dir)
44
46
 
45
47
  # List all directories in tools/
@@ -53,20 +55,20 @@ module Ukiryu
53
55
  # Get available versions for a tool (cached)
54
56
  #
55
57
  # @param name [String, Symbol] the tool name
56
- # @param registry_path [String, nil] the registry path
58
+ # @param register_path [String, nil] the register path
57
59
  # @return [Hash] mapping of version filename to Gem::Version
58
- def list_versions(name, registry_path: nil)
59
- registry_path ||= @default_registry_path
60
- return {} unless registry_path
60
+ def list_versions(name, register_path: nil)
61
+ register_path ||= effective_register_path
62
+ return {} unless register_path
61
63
 
62
64
  # Initialize cache
63
65
  @version_cache ||= {}
64
- @registry_cache_key ||= registry_path
66
+ @register_cache_key ||= register_path
65
67
 
66
- # Clear cache if registry path changed
67
- if @registry_cache_key != registry_path
68
+ # Clear cache if register path changed
69
+ if @register_cache_key != register_path
68
70
  @version_cache.clear
69
- @registry_cache_key = registry_path
71
+ @register_cache_key = register_path
70
72
  end
71
73
 
72
74
  # Check cache
@@ -74,7 +76,7 @@ module Ukiryu
74
76
  return @version_cache[cache_key].dup if @version_cache[cache_key]
75
77
 
76
78
  # Build version list
77
- versions = scan_tool_versions(name, registry_path)
79
+ versions = scan_tool_versions(name, register_path)
78
80
  @version_cache[cache_key] = versions
79
81
 
80
82
  versions.dup
@@ -88,16 +90,16 @@ module Ukiryu
88
90
  # @param name [String, Symbol] the tool name or interface name
89
91
  # @param options [Hash] loading options
90
92
  # @option options [String] :version specific version to load
91
- # @option options [String] :registry_path path to registry
93
+ # @option options [String] :register_path path to register
92
94
  # @return [ToolMetadata, nil] the tool metadata or nil if not found
93
95
  def load_tool_metadata(name, options = {})
94
- registry_path = options[:registry_path] || @default_registry_path
96
+ register_path = options[:register_path] || effective_register_path
95
97
 
96
98
  # First try exact name match
97
- yaml_content = load_tool_yaml(name, options.merge(registry_path: registry_path))
99
+ yaml_content = load_tool_yaml(name, options.merge(register_path: register_path))
98
100
  if yaml_content
99
101
  hash = YAML.safe_load(yaml_content, permitted_classes: [Symbol])
100
- return ToolMetadata.from_hash(hash, tool_name: name.to_s, registry_path: registry_path) if hash
102
+ return ToolMetadata.from_hash(hash, tool_name: name.to_s, register_path: register_path) if hash
101
103
  end
102
104
 
103
105
  # If not found, try interface-based discovery using ToolIndex
@@ -110,12 +112,12 @@ module Ukiryu
110
112
  # @param name [String, Symbol] the tool name
111
113
  # @param options [Hash] loading options
112
114
  # @option options [String] :version specific version to load
113
- # @option options [String] :registry_path path to registry
115
+ # @option options [String] :register_path path to register
114
116
  # @return [String, nil] the YAML content or nil if not found
115
117
  def load_tool_yaml(name, options = {})
116
- registry_path = options[:registry_path] || @default_registry_path
118
+ register_path = options[:register_path] || effective_register_path
117
119
 
118
- return nil unless registry_path
120
+ return nil unless register_path
119
121
 
120
122
  # Convert to string for path operations
121
123
  name_str = name.to_s
@@ -123,16 +125,16 @@ module Ukiryu
123
125
  # Try version-specific directory first
124
126
  version = options[:version]
125
127
  if version
126
- file = File.join(registry_path, 'tools', name_str, "#{version}.yaml")
128
+ file = File.join(register_path, 'tools', name_str, "#{version}.yaml")
127
129
  return File.read(file) if File.exist?(file)
128
130
  end
129
131
 
130
132
  # Use cached version list if available
131
- versions = list_versions(name_str, registry_path: registry_path)
133
+ versions = list_versions(name_str, register_path: register_path)
132
134
 
133
135
  if versions.empty?
134
136
  # Try the old format (single file per tool)
135
- file = File.join(registry_path, 'tools', "#{name_str}.yaml")
137
+ file = File.join(register_path, 'tools', "#{name_str}.yaml")
136
138
  return File.read(file) if File.exist?(file)
137
139
 
138
140
  return nil
@@ -153,7 +155,7 @@ module Ukiryu
153
155
  # @param name [String, Symbol] the tool name
154
156
  # @param options [Hash] validation options
155
157
  # @option options [String] :version specific version to validate
156
- # @option options [String] :registry_path path to registry
158
+ # @option options [String] :register_path path to register
157
159
  # @option options [String] :schema_path path to schema file
158
160
  # @return [ValidationResult] the validation result
159
161
  def validate_tool(name, options = {})
@@ -171,10 +173,10 @@ module Ukiryu
171
173
  end
172
174
  end
173
175
 
174
- # Validate all tool profiles in the registry
176
+ # Validate all tool profiles in the register
175
177
  #
176
178
  # @param options [Hash] validation options
177
- # @option options [String] :registry_path path to registry
179
+ # @option options [String] :register_path path to register
178
180
  # @option options [String] :schema_path path to schema file
179
181
  # @return [Array<ValidationResult>] list of validation results
180
182
  def validate_all_tools(options = {})
@@ -185,13 +187,27 @@ module Ukiryu
185
187
 
186
188
  private
187
189
 
190
+ # Get the effective register path
191
+ #
192
+ # Returns the manually set path if available, otherwise uses
193
+ # RegisterAutoManager to get or create the default path.
194
+ #
195
+ # @return [String, nil] the register path, or nil if unavailable
196
+ def effective_register_path
197
+ # If manually set, use that
198
+ return @default_register_path if @default_register_path
199
+
200
+ # Otherwise, use RegisterAutoManager (auto-clone if needed)
201
+ RegisterAutoManager.register_path
202
+ end
203
+
188
204
  # Scan tool versions and sort by Gem::Version
189
205
  #
190
206
  # @param name [String] the tool name
191
- # @param registry_path [String] the registry path
207
+ # @param register_path [String] the register path
192
208
  # @return [Hash] mapping of version filename to Gem::Version
193
- def scan_tool_versions(name, registry_path)
194
- pattern = File.join(registry_path, 'tools', name.to_s, '*.yaml')
209
+ def scan_tool_versions(name, register_path)
210
+ pattern = File.join(register_path, 'tools', name.to_s, '*.yaml')
195
211
  files = Dir.glob(pattern)
196
212
 
197
213
  # Sort files by Gem::Version for proper version ordering