ace-support-nav 0.25.0
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.
- checksums.yaml +7 -0
- data/.ace-defaults/nav/config.yml +33 -0
- data/.ace-defaults/nav/protocols/guide-sources/ace-support-nav.yml +7 -0
- data/.ace-defaults/nav/protocols/guide.yml +69 -0
- data/.ace-defaults/nav/protocols/prompt.yml +39 -0
- data/.ace-defaults/nav/protocols/skill-sources/ace-support-nav.yml +19 -0
- data/.ace-defaults/nav/protocols/skill.yml +22 -0
- data/.ace-defaults/nav/protocols/tmpl-sources/ace-support-nav.yml +7 -0
- data/.ace-defaults/nav/protocols/tmpl.yml +55 -0
- data/.ace-defaults/nav/protocols/wfi-sources/ace-support-nav.yml +7 -0
- data/.ace-defaults/nav/protocols/wfi.yml +61 -0
- data/CHANGELOG.md +231 -0
- data/LICENSE +21 -0
- data/README.md +48 -0
- data/Rakefile +12 -0
- data/docs/demo/ace-support-nav-getting-started.gif +0 -0
- data/docs/demo/ace-support-nav-getting-started.tape.yml +28 -0
- data/exe/ace-nav +49 -0
- data/handbook/workflow-instructions/test.wfi.md +14 -0
- data/lib/ace/support/nav/atoms/extension_inferrer.rb +134 -0
- data/lib/ace/support/nav/atoms/gem_resolver.rb +59 -0
- data/lib/ace/support/nav/atoms/path_normalizer.rb +52 -0
- data/lib/ace/support/nav/atoms/uri_parser.rb +62 -0
- data/lib/ace/support/nav/cli/commands/create.rb +114 -0
- data/lib/ace/support/nav/cli/commands/list.rb +122 -0
- data/lib/ace/support/nav/cli/commands/resolve.rb +187 -0
- data/lib/ace/support/nav/cli/commands/sources.rb +112 -0
- data/lib/ace/support/nav/cli.rb +66 -0
- data/lib/ace/support/nav/models/handbook_source.rb +73 -0
- data/lib/ace/support/nav/models/protocol_source.rb +104 -0
- data/lib/ace/support/nav/models/resource.rb +46 -0
- data/lib/ace/support/nav/models/resource_uri.rb +78 -0
- data/lib/ace/support/nav/molecules/config_loader.rb +275 -0
- data/lib/ace/support/nav/molecules/handbook_scanner.rb +204 -0
- data/lib/ace/support/nav/molecules/protocol_scanner.rb +434 -0
- data/lib/ace/support/nav/molecules/resource_resolver.rb +134 -0
- data/lib/ace/support/nav/molecules/source_registry.rb +133 -0
- data/lib/ace/support/nav/organisms/command_delegator.rb +122 -0
- data/lib/ace/support/nav/organisms/navigation_engine.rb +180 -0
- data/lib/ace/support/nav/version.rb +9 -0
- data/lib/ace/support/nav.rb +104 -0
- metadata +228 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "shellwords"
|
|
4
|
+
require_relative "../molecules/config_loader"
|
|
5
|
+
|
|
6
|
+
module Ace
|
|
7
|
+
module Support
|
|
8
|
+
module Nav
|
|
9
|
+
module Organisms
|
|
10
|
+
# Handles command delegation for cmd-type protocols
|
|
11
|
+
# Executes external commands based on protocol configuration templates
|
|
12
|
+
class CommandDelegator
|
|
13
|
+
def initialize(config_loader: nil)
|
|
14
|
+
@config_loader = config_loader || Molecules::ConfigLoader.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Delegate a URI to an external command
|
|
18
|
+
# @param uri_string [String] The URI to delegate (e.g., "task://083")
|
|
19
|
+
# @param options [Hash] Options from CLI (e.g., {path: true, content: true})
|
|
20
|
+
# @return [Integer] Exit code from the delegated command
|
|
21
|
+
def delegate(uri_string, options = {})
|
|
22
|
+
# Parse the URI to extract protocol and reference
|
|
23
|
+
protocol, reference = parse_uri(uri_string)
|
|
24
|
+
|
|
25
|
+
# Load protocol configuration
|
|
26
|
+
protocol_config = @config_loader.load_protocol_config(protocol)
|
|
27
|
+
|
|
28
|
+
# Verify this is a cmd-type protocol
|
|
29
|
+
unless protocol_config["type"] == "cmd"
|
|
30
|
+
raise ArgumentError, "Protocol #{protocol} is not a cmd-type protocol"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Get command template
|
|
34
|
+
command_template = protocol_config["command_template"]
|
|
35
|
+
unless command_template
|
|
36
|
+
raise ArgumentError, "Protocol #{protocol} missing command_template"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Build the command
|
|
40
|
+
command_parts = build_command(command_template, reference, options, protocol_config)
|
|
41
|
+
|
|
42
|
+
# Execute the command
|
|
43
|
+
execute_command(command_parts)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
# Parse a URI into protocol and reference
|
|
49
|
+
# @param uri_string [String] URI like "task://083" or "task://v.0.9.0+task.083"
|
|
50
|
+
# @return [Array<String, String>] [protocol, reference]
|
|
51
|
+
def parse_uri(uri_string)
|
|
52
|
+
unless uri_string.include?("://")
|
|
53
|
+
raise ArgumentError, "Invalid URI format: #{uri_string}"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
parts = uri_string.split("://", 2)
|
|
57
|
+
protocol = parts[0]
|
|
58
|
+
reference = parts[1] || ""
|
|
59
|
+
|
|
60
|
+
[protocol, reference]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Build command array from template and options
|
|
64
|
+
# @param template [String] Command template with %{ref} placeholder
|
|
65
|
+
# @param reference [String] The resource reference to substitute
|
|
66
|
+
# @param options [Hash] CLI options to pass through
|
|
67
|
+
# @param protocol_config [Hash] Protocol configuration
|
|
68
|
+
# @return [Array<String>] Command parts as array for safe execution
|
|
69
|
+
#
|
|
70
|
+
# @note Template parsing uses Shellwords.split() for robust parsing of command
|
|
71
|
+
# templates, properly handling quoted strings and complex argument patterns.
|
|
72
|
+
def build_command(template, reference, options, protocol_config)
|
|
73
|
+
# Substitute reference in template
|
|
74
|
+
command_string = template.gsub("%{ref}", reference)
|
|
75
|
+
|
|
76
|
+
# Parse command using Shellwords for robust handling of quotes and spaces
|
|
77
|
+
command_parts = Shellwords.split(command_string)
|
|
78
|
+
|
|
79
|
+
# Add pass-through options
|
|
80
|
+
pass_through_options = protocol_config["pass_through_options"] || []
|
|
81
|
+
|
|
82
|
+
options.each do |key, value|
|
|
83
|
+
option_flag = "--#{key.to_s.tr("_", "-")}"
|
|
84
|
+
|
|
85
|
+
# Only add if it's in pass_through list or if we don't have a list
|
|
86
|
+
if pass_through_options.empty? || pass_through_options.include?(option_flag)
|
|
87
|
+
if value == true
|
|
88
|
+
command_parts << option_flag
|
|
89
|
+
elsif value.is_a?(String)
|
|
90
|
+
command_parts << option_flag
|
|
91
|
+
command_parts << value
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
command_parts
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Execute command using system and return exit code
|
|
100
|
+
# @param command_parts [Array<String>] Command parts for safe execution
|
|
101
|
+
# @return [Integer] Exit code (0 for success, 1 for failure)
|
|
102
|
+
def execute_command(command_parts)
|
|
103
|
+
# Use system with array argument for safety (no shell interpolation)
|
|
104
|
+
success = system(*command_parts)
|
|
105
|
+
|
|
106
|
+
# Return exit code
|
|
107
|
+
if success.nil?
|
|
108
|
+
# Command not found
|
|
109
|
+
warn "Error: Command not found: #{command_parts[0]}"
|
|
110
|
+
warn "Please install the required gem or ensure it's in your PATH"
|
|
111
|
+
1
|
|
112
|
+
elsif success
|
|
113
|
+
0
|
|
114
|
+
else
|
|
115
|
+
$?.exitstatus || 1
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../molecules/protocol_scanner"
|
|
4
|
+
require_relative "../molecules/resource_resolver"
|
|
5
|
+
require_relative "../atoms/path_normalizer"
|
|
6
|
+
|
|
7
|
+
module Ace
|
|
8
|
+
module Support
|
|
9
|
+
module Nav
|
|
10
|
+
module Organisms
|
|
11
|
+
# Orchestrates navigation operations
|
|
12
|
+
class NavigationEngine
|
|
13
|
+
def initialize(handbook_scanner: nil, protocol_scanner: nil, resource_resolver: nil, path_normalizer: nil)
|
|
14
|
+
# Support legacy handbook_scanner parameter
|
|
15
|
+
@protocol_scanner = protocol_scanner || handbook_scanner || Molecules::ProtocolScanner.new
|
|
16
|
+
@resource_resolver = resource_resolver || Molecules::ResourceResolver.new(protocol_scanner: @protocol_scanner)
|
|
17
|
+
@path_normalizer = path_normalizer || Atoms::PathNormalizer.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Resolve a single resource URI to a path
|
|
21
|
+
def resolve(uri_string, options = {})
|
|
22
|
+
resource = @resource_resolver.resolve(uri_string)
|
|
23
|
+
return nil unless resource
|
|
24
|
+
|
|
25
|
+
if options[:content]
|
|
26
|
+
resource.content
|
|
27
|
+
elsif options[:verbose]
|
|
28
|
+
resource.to_h
|
|
29
|
+
else
|
|
30
|
+
resource.path
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# List resources matching a pattern
|
|
35
|
+
def list(uri_pattern, options = {})
|
|
36
|
+
resources = @resource_resolver.resolve_pattern(uri_pattern)
|
|
37
|
+
|
|
38
|
+
if options[:tree]
|
|
39
|
+
format_as_tree(resources)
|
|
40
|
+
elsif options[:verbose]
|
|
41
|
+
resources.map(&:to_h)
|
|
42
|
+
else
|
|
43
|
+
format_as_list(resources)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Create a new resource from a template
|
|
48
|
+
def create(uri_string, target_path = nil)
|
|
49
|
+
# Resolve the template
|
|
50
|
+
template = @resource_resolver.resolve(uri_string)
|
|
51
|
+
return {error: "Template not found: #{uri_string}"} unless template
|
|
52
|
+
|
|
53
|
+
# Determine target path
|
|
54
|
+
target = determine_target_path(template, target_path)
|
|
55
|
+
return {error: "Could not determine target path"} unless target
|
|
56
|
+
|
|
57
|
+
# Create directory if needed
|
|
58
|
+
target_dir = File.dirname(target)
|
|
59
|
+
FileUtils.mkdir_p(target_dir) unless Dir.exist?(target_dir)
|
|
60
|
+
|
|
61
|
+
# Copy template content
|
|
62
|
+
if template.content
|
|
63
|
+
File.write(target, template.content)
|
|
64
|
+
{created: target, from: template.path}
|
|
65
|
+
else
|
|
66
|
+
{error: "Template has no content: #{template.path}"}
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Show available sources
|
|
71
|
+
def sources(options = {})
|
|
72
|
+
all_sources = @protocol_scanner.scan_all_sources
|
|
73
|
+
|
|
74
|
+
if options[:verbose]
|
|
75
|
+
all_sources.map(&:to_h)
|
|
76
|
+
else
|
|
77
|
+
all_sources.map { |s| "#{s.alias_name} (#{s.type}): #{s.path}" }
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Get all discovered protocols
|
|
82
|
+
def discovered_protocols
|
|
83
|
+
config_loader.discovered_protocols
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Check if a protocol is cmd-type (command delegation)
|
|
87
|
+
# @param protocol_name [String] The protocol name to check
|
|
88
|
+
# @return [Boolean] true if protocol delegates to external command
|
|
89
|
+
def cmd_protocol?(protocol_name)
|
|
90
|
+
config_loader.protocol_type(protocol_name) == "cmd"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Resolve a cmd-type protocol URI by running its command and capturing stdout
|
|
94
|
+
# Used by tools that need to programmatically obtain the resolved path
|
|
95
|
+
# @param uri_string [String] e.g., "task://8c0.t.05p"
|
|
96
|
+
# @return [String, nil] captured stdout (path), or nil on failure
|
|
97
|
+
def resolve_cmd_to_path(uri_string)
|
|
98
|
+
protocol, reference = uri_string.split("://", 2)
|
|
99
|
+
return nil unless cmd_protocol?(protocol)
|
|
100
|
+
|
|
101
|
+
protocol_config = config_loader.load_protocol_config(protocol)
|
|
102
|
+
command_template = protocol_config["command_template"]
|
|
103
|
+
return nil unless command_template
|
|
104
|
+
|
|
105
|
+
require "open3"
|
|
106
|
+
require "shellwords"
|
|
107
|
+
require "timeout"
|
|
108
|
+
args = Shellwords.split(command_template.gsub("%{ref}", Shellwords.escape(reference)))
|
|
109
|
+
stdout, status = Timeout.timeout(10) { Open3.capture2(*args) }
|
|
110
|
+
return nil unless status.success?
|
|
111
|
+
|
|
112
|
+
result = stdout.strip
|
|
113
|
+
result.empty? ? nil : result
|
|
114
|
+
rescue Timeout::Error
|
|
115
|
+
warn "Warning: cmd protocol timed out for '#{uri_string}'"
|
|
116
|
+
nil
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
private
|
|
120
|
+
|
|
121
|
+
def format_as_list(resources)
|
|
122
|
+
resources.map do |resource|
|
|
123
|
+
"#{resource.uri} → #{resource.path} (#{resource.source.alias_name})"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def format_as_tree(resources)
|
|
128
|
+
# Group by source
|
|
129
|
+
by_source = resources.group_by { |r| r.source.alias_name }
|
|
130
|
+
|
|
131
|
+
tree = []
|
|
132
|
+
by_source.each do |source_alias, source_resources|
|
|
133
|
+
tree << "#{source_alias}/"
|
|
134
|
+
|
|
135
|
+
# Group by protocol
|
|
136
|
+
by_protocol = source_resources.group_by(&:protocol)
|
|
137
|
+
by_protocol.each do |protocol, protocol_resources|
|
|
138
|
+
tree << " #{protocol}://"
|
|
139
|
+
|
|
140
|
+
# Sort and display resources
|
|
141
|
+
protocol_resources.sort_by(&:resource_path).each do |resource|
|
|
142
|
+
tree << " #{resource.resource_path}"
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
tree
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def determine_target_path(template, target_path)
|
|
151
|
+
# If explicit target provided, use it
|
|
152
|
+
return @path_normalizer.normalize(target_path) if target_path
|
|
153
|
+
|
|
154
|
+
# Otherwise, create in project .ace-handbook
|
|
155
|
+
project_handbook = File.expand_path("./.ace-handbook")
|
|
156
|
+
|
|
157
|
+
# Determine subdirectory based on protocol
|
|
158
|
+
subdir = case template.protocol
|
|
159
|
+
when "wfi" then "workflow-instructions"
|
|
160
|
+
when "tmpl" then "templates"
|
|
161
|
+
when "guide" then "guides"
|
|
162
|
+
when "sample" then "samples"
|
|
163
|
+
else template.protocol
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Build target path
|
|
167
|
+
filename = File.basename(template.path)
|
|
168
|
+
File.join(project_handbook, subdir, filename)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Access the config_loader from protocol_scanner
|
|
172
|
+
# Reuses the same ConfigLoader instance across all protocol operations
|
|
173
|
+
def config_loader
|
|
174
|
+
@protocol_scanner.config_loader
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "nav/version"
|
|
4
|
+
require "ace/support/config"
|
|
5
|
+
|
|
6
|
+
# Load all ace-support-nav components
|
|
7
|
+
require_relative "nav/cli"
|
|
8
|
+
require_relative "nav/atoms/gem_resolver"
|
|
9
|
+
require_relative "nav/atoms/path_normalizer"
|
|
10
|
+
require_relative "nav/atoms/uri_parser"
|
|
11
|
+
require_relative "nav/molecules/config_loader"
|
|
12
|
+
require_relative "nav/molecules/handbook_scanner"
|
|
13
|
+
require_relative "nav/molecules/protocol_scanner"
|
|
14
|
+
require_relative "nav/molecules/resource_resolver"
|
|
15
|
+
require_relative "nav/molecules/source_registry"
|
|
16
|
+
require_relative "nav/organisms/navigation_engine"
|
|
17
|
+
require_relative "nav/organisms/command_delegator"
|
|
18
|
+
require_relative "nav/models/handbook_source"
|
|
19
|
+
require_relative "nav/models/protocol_source"
|
|
20
|
+
require_relative "nav/models/resource"
|
|
21
|
+
require_relative "nav/models/resource_uri"
|
|
22
|
+
|
|
23
|
+
module Ace
|
|
24
|
+
module Support
|
|
25
|
+
module Nav
|
|
26
|
+
class Error < StandardError; end
|
|
27
|
+
|
|
28
|
+
# Initialize mutex for thread-safe config access
|
|
29
|
+
@config_mutex = Mutex.new
|
|
30
|
+
|
|
31
|
+
# Returns the gem root directory
|
|
32
|
+
# Used by command files to locate .ace-defaults/ configuration
|
|
33
|
+
# Centralizes the path calculation to avoid duplication across commands
|
|
34
|
+
# @return [String] Path to the gem root directory
|
|
35
|
+
def self.gem_root
|
|
36
|
+
@gem_root ||= Gem.loaded_specs["ace-support-nav"]&.gem_dir ||
|
|
37
|
+
File.expand_path("../../..", __dir__)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Check if debug mode is enabled
|
|
41
|
+
# @return [Boolean] True if debug mode is enabled
|
|
42
|
+
def self.debug?
|
|
43
|
+
ENV["ACE_DEBUG"] == "1" || ENV["DEBUG"] == "1"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Load ace-support-nav configuration using ace-config cascade
|
|
47
|
+
# Follows ADR-022: Configuration Default and Override Pattern
|
|
48
|
+
# Uses Ace::Support::Config.create() for configuration cascade resolution
|
|
49
|
+
# Thread-safe: uses mutex for initialization
|
|
50
|
+
# @return [Hash] Configuration hash with defaults merged
|
|
51
|
+
def self.config
|
|
52
|
+
# Fast path: return cached config if already initialized
|
|
53
|
+
return @config if defined?(@config) && @config
|
|
54
|
+
|
|
55
|
+
# Thread-safe initialization
|
|
56
|
+
@config_mutex.synchronize do
|
|
57
|
+
@config ||= load_config
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Reset config cache (useful for testing)
|
|
62
|
+
# Thread-safe: uses mutex to prevent race conditions
|
|
63
|
+
def self.reset_config!
|
|
64
|
+
@config_mutex.synchronize do
|
|
65
|
+
@config = nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Load configuration using Ace::Support::Config cascade
|
|
70
|
+
# @return [Hash] Merged configuration
|
|
71
|
+
def self.load_config
|
|
72
|
+
resolver = Ace::Support::Config.create(
|
|
73
|
+
config_dir: ".ace",
|
|
74
|
+
defaults_dir: ".ace-defaults",
|
|
75
|
+
gem_path: gem_root
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Resolve config for nav namespace
|
|
79
|
+
config = resolver.resolve_namespace("nav")
|
|
80
|
+
config.data
|
|
81
|
+
rescue => e
|
|
82
|
+
warn "ace-support-nav: Could not load config: #{e.class} - #{e.message}" if debug?
|
|
83
|
+
# Fall back to gem defaults instead of empty hash to prevent silent config erasure
|
|
84
|
+
load_gem_defaults_fallback
|
|
85
|
+
end
|
|
86
|
+
private_class_method :load_config
|
|
87
|
+
|
|
88
|
+
# Load gem defaults directly as fallback when cascade resolution fails
|
|
89
|
+
# This ensures configuration is never silently erased due to YAML errors
|
|
90
|
+
# or user config issues
|
|
91
|
+
# @return [Hash] Defaults hash or empty hash if defaults also fail
|
|
92
|
+
def self.load_gem_defaults_fallback
|
|
93
|
+
defaults_path = File.join(gem_root, ".ace-defaults", "nav", "config.yml")
|
|
94
|
+
|
|
95
|
+
return {} unless File.exist?(defaults_path)
|
|
96
|
+
|
|
97
|
+
YAML.safe_load_file(defaults_path, permitted_classes: [Date], aliases: true) || {}
|
|
98
|
+
rescue
|
|
99
|
+
{} # Only return empty hash if even defaults fail to load
|
|
100
|
+
end
|
|
101
|
+
private_class_method :load_gem_defaults_fallback
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ace-support-nav
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.25.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Michal Czyz
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: ace-support-cli
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0.3'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0.3'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: ace-support-core
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.25'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.25'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: ace-support-config
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0.8'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0.8'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: ace-support-fs
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.2'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.2'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: ace-support-test-helpers
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0.12'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0.12'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: bundler
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '2.0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '2.0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: minitest
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '5.0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '5.0'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: rake
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '13.0'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '13.0'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: rubocop
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '1.50'
|
|
131
|
+
type: :development
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '1.50'
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: simplecov
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - "~>"
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '0.22'
|
|
145
|
+
type: :development
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - "~>"
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '0.22'
|
|
152
|
+
description: ace-support-nav provides unified navigation and path resolution across
|
|
153
|
+
the ACE ecosystem. It automatically discovers handbooks bundled within ace-* gems,
|
|
154
|
+
resolves resource URIs to actual file paths, and supports a multi-level override
|
|
155
|
+
cascade.
|
|
156
|
+
email:
|
|
157
|
+
- mc@cs3b.com
|
|
158
|
+
executables:
|
|
159
|
+
- ace-nav
|
|
160
|
+
extensions: []
|
|
161
|
+
extra_rdoc_files: []
|
|
162
|
+
files:
|
|
163
|
+
- ".ace-defaults/nav/config.yml"
|
|
164
|
+
- ".ace-defaults/nav/protocols/guide-sources/ace-support-nav.yml"
|
|
165
|
+
- ".ace-defaults/nav/protocols/guide.yml"
|
|
166
|
+
- ".ace-defaults/nav/protocols/prompt.yml"
|
|
167
|
+
- ".ace-defaults/nav/protocols/skill-sources/ace-support-nav.yml"
|
|
168
|
+
- ".ace-defaults/nav/protocols/skill.yml"
|
|
169
|
+
- ".ace-defaults/nav/protocols/tmpl-sources/ace-support-nav.yml"
|
|
170
|
+
- ".ace-defaults/nav/protocols/tmpl.yml"
|
|
171
|
+
- ".ace-defaults/nav/protocols/wfi-sources/ace-support-nav.yml"
|
|
172
|
+
- ".ace-defaults/nav/protocols/wfi.yml"
|
|
173
|
+
- CHANGELOG.md
|
|
174
|
+
- LICENSE
|
|
175
|
+
- README.md
|
|
176
|
+
- Rakefile
|
|
177
|
+
- docs/demo/ace-support-nav-getting-started.gif
|
|
178
|
+
- docs/demo/ace-support-nav-getting-started.tape.yml
|
|
179
|
+
- exe/ace-nav
|
|
180
|
+
- handbook/workflow-instructions/test.wfi.md
|
|
181
|
+
- lib/ace/support/nav.rb
|
|
182
|
+
- lib/ace/support/nav/atoms/extension_inferrer.rb
|
|
183
|
+
- lib/ace/support/nav/atoms/gem_resolver.rb
|
|
184
|
+
- lib/ace/support/nav/atoms/path_normalizer.rb
|
|
185
|
+
- lib/ace/support/nav/atoms/uri_parser.rb
|
|
186
|
+
- lib/ace/support/nav/cli.rb
|
|
187
|
+
- lib/ace/support/nav/cli/commands/create.rb
|
|
188
|
+
- lib/ace/support/nav/cli/commands/list.rb
|
|
189
|
+
- lib/ace/support/nav/cli/commands/resolve.rb
|
|
190
|
+
- lib/ace/support/nav/cli/commands/sources.rb
|
|
191
|
+
- lib/ace/support/nav/models/handbook_source.rb
|
|
192
|
+
- lib/ace/support/nav/models/protocol_source.rb
|
|
193
|
+
- lib/ace/support/nav/models/resource.rb
|
|
194
|
+
- lib/ace/support/nav/models/resource_uri.rb
|
|
195
|
+
- lib/ace/support/nav/molecules/config_loader.rb
|
|
196
|
+
- lib/ace/support/nav/molecules/handbook_scanner.rb
|
|
197
|
+
- lib/ace/support/nav/molecules/protocol_scanner.rb
|
|
198
|
+
- lib/ace/support/nav/molecules/resource_resolver.rb
|
|
199
|
+
- lib/ace/support/nav/molecules/source_registry.rb
|
|
200
|
+
- lib/ace/support/nav/organisms/command_delegator.rb
|
|
201
|
+
- lib/ace/support/nav/organisms/navigation_engine.rb
|
|
202
|
+
- lib/ace/support/nav/version.rb
|
|
203
|
+
homepage: https://github.com/cs3b/ace
|
|
204
|
+
licenses:
|
|
205
|
+
- MIT
|
|
206
|
+
metadata:
|
|
207
|
+
allowed_push_host: https://rubygems.org
|
|
208
|
+
homepage_uri: https://github.com/cs3b/ace
|
|
209
|
+
source_code_uri: https://github.com/cs3b/ace/tree/main/ace-support-nav/
|
|
210
|
+
changelog_uri: https://github.com/cs3b/ace/blob/main/ace-support-nav/CHANGELOG.md
|
|
211
|
+
rdoc_options: []
|
|
212
|
+
require_paths:
|
|
213
|
+
- lib
|
|
214
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
215
|
+
requirements:
|
|
216
|
+
- - ">="
|
|
217
|
+
- !ruby/object:Gem::Version
|
|
218
|
+
version: 3.2.0
|
|
219
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
|
+
requirements:
|
|
221
|
+
- - ">="
|
|
222
|
+
- !ruby/object:Gem::Version
|
|
223
|
+
version: '0'
|
|
224
|
+
requirements: []
|
|
225
|
+
rubygems_version: 3.6.9
|
|
226
|
+
specification_version: 4
|
|
227
|
+
summary: Unified navigation and resource discovery for ACE ecosystem
|
|
228
|
+
test_files: []
|