ace-bundle 0.40.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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.ace-defaults/bundle/config.yml +28 -0
  3. data/.ace-defaults/bundle/presets/base.md +15 -0
  4. data/.ace-defaults/bundle/presets/code-review.md +61 -0
  5. data/.ace-defaults/bundle/presets/development.md +16 -0
  6. data/.ace-defaults/bundle/presets/documentation-review.md +52 -0
  7. data/.ace-defaults/bundle/presets/mixed-content-example.md +94 -0
  8. data/.ace-defaults/bundle/presets/project-context.md +79 -0
  9. data/.ace-defaults/bundle/presets/project.md +35 -0
  10. data/.ace-defaults/bundle/presets/section-example-simple.md +27 -0
  11. data/.ace-defaults/bundle/presets/security-review.md +53 -0
  12. data/.ace-defaults/bundle/presets/simple-project.md +43 -0
  13. data/.ace-defaults/bundle/presets/team.md +18 -0
  14. data/.ace-defaults/nav/protocols/wfi-sources/ace-bundle.yml +19 -0
  15. data/CHANGELOG.md +384 -0
  16. data/LICENSE +21 -0
  17. data/README.md +40 -0
  18. data/Rakefile +22 -0
  19. data/exe/ace-bundle +14 -0
  20. data/handbook/skills/as-bundle/SKILL.md +28 -0
  21. data/handbook/skills/as-onboard/SKILL.md +33 -0
  22. data/handbook/workflow-instructions/bundle.wf.md +111 -0
  23. data/handbook/workflow-instructions/onboard.wf.md +20 -0
  24. data/lib/ace/bundle/atoms/boundary_finder.rb +122 -0
  25. data/lib/ace/bundle/atoms/bundle_normalizer.rb +128 -0
  26. data/lib/ace/bundle/atoms/content_checker.rb +46 -0
  27. data/lib/ace/bundle/atoms/line_counter.rb +37 -0
  28. data/lib/ace/bundle/atoms/preset_list_formatter.rb +44 -0
  29. data/lib/ace/bundle/atoms/preset_validator.rb +69 -0
  30. data/lib/ace/bundle/atoms/section_validator.rb +215 -0
  31. data/lib/ace/bundle/atoms/typo_detector.rb +76 -0
  32. data/lib/ace/bundle/cli/commands/load.rb +347 -0
  33. data/lib/ace/bundle/cli.rb +26 -0
  34. data/lib/ace/bundle/models/bundle_data.rb +75 -0
  35. data/lib/ace/bundle/molecules/bundle_chunker.rb +280 -0
  36. data/lib/ace/bundle/molecules/bundle_file_writer.rb +269 -0
  37. data/lib/ace/bundle/molecules/bundle_merger.rb +248 -0
  38. data/lib/ace/bundle/molecules/preset_manager.rb +331 -0
  39. data/lib/ace/bundle/molecules/section_compressor.rb +249 -0
  40. data/lib/ace/bundle/molecules/section_formatter.rb +580 -0
  41. data/lib/ace/bundle/molecules/section_processor.rb +460 -0
  42. data/lib/ace/bundle/organisms/bundle_loader.rb +1436 -0
  43. data/lib/ace/bundle/organisms/pr_bundle_loader.rb +147 -0
  44. data/lib/ace/bundle/version.rb +7 -0
  45. data/lib/ace/bundle.rb +251 -0
  46. metadata +190 -0
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ace/git"
4
+
5
+ module Ace
6
+ module Bundle
7
+ module Organisms
8
+ # Loads PR diff content into bundle
9
+ #
10
+ # Responsible for:
11
+ # - Normalizing PR references (string, array, hash formats)
12
+ # - Fetching diffs via Ace::Git::Molecules::PrMetadataFetcher
13
+ # - Integrating results into bundle sections
14
+ # - Error handling and surfacing
15
+ #
16
+ # @example Basic usage
17
+ # loader = PrBundleLoader.new(timeout: 60)
18
+ # loader.process(bundle, ["123", "owner/repo#456"])
19
+ #
20
+ class PrBundleLoader
21
+ # @param options [Hash] Configuration options
22
+ # @option options [Integer] :timeout Timeout for gh commands (default from ace-git config)
23
+ # @option options [Boolean] :debug Enable debug output
24
+ def initialize(options = {})
25
+ @timeout = options[:timeout] || Ace::Git.network_timeout
26
+ @debug = options[:debug] || false
27
+ end
28
+
29
+ # Process PR references and add diffs to bundle
30
+ #
31
+ # @param bundle [Models::BundleData] Bundle to populate
32
+ # @param pr_refs [Array<String>, String, Hash, nil] PR reference(s)
33
+ # @return [Boolean] true if at least one diff was successfully fetched
34
+ def process(bundle, pr_refs)
35
+ normalized = normalize_pr_refs(pr_refs)
36
+ return false if normalized.empty?
37
+
38
+ processed_diffs = fetch_all_diffs(bundle, normalized)
39
+ successful_diffs = processed_diffs.select { |d| d[:success] }
40
+
41
+ if successful_diffs.empty?
42
+ surface_errors_to_content(bundle)
43
+ return false
44
+ end
45
+
46
+ add_diffs_to_bundle(bundle, processed_diffs)
47
+ true
48
+ end
49
+
50
+ private
51
+
52
+ # Normalize PR refs to array, deduplicate, and remove empty/nil values
53
+ # Handles both string refs and hash refs (for future extensibility)
54
+ #
55
+ # @param pr_refs [String, Array, Hash, nil] PR reference(s)
56
+ # @return [Array<String>] Normalized, deduplicated PR refs
57
+ def normalize_pr_refs(pr_refs)
58
+ refs = pr_refs.is_a?(Array) ? pr_refs.flatten : [pr_refs]
59
+ refs.map do |ref|
60
+ case ref
61
+ when String then ref.strip
62
+ when Hash then ref[:number]&.to_s || ref["number"]&.to_s
63
+ else ref&.to_s
64
+ end
65
+ end.compact.reject(&:empty?).uniq
66
+ end
67
+
68
+ # Fetch diffs for all PR refs, recording errors in bundle metadata
69
+ #
70
+ # @param bundle [Models::BundleData] Bundle for error recording
71
+ # @param pr_refs [Array<String>] Normalized PR refs
72
+ # @return [Array<Hash>] Processed diff results
73
+ def fetch_all_diffs(bundle, pr_refs)
74
+ pr_refs.map do |pr_ref|
75
+ fetch_single_diff(bundle, pr_ref)
76
+ end.compact
77
+ end
78
+
79
+ # Fetch diff for a single PR reference
80
+ #
81
+ # @param bundle [Models::BundleData] Bundle for error recording
82
+ # @param pr_ref [String] Single PR reference
83
+ # @return [Hash, nil] Diff result or nil on skip
84
+ def fetch_single_diff(bundle, pr_ref)
85
+ result = Ace::Git::Molecules::PrMetadataFetcher.fetch_diff(pr_ref, timeout: @timeout)
86
+
87
+ if result[:success]
88
+ {
89
+ range: result[:source],
90
+ output: result[:diff],
91
+ success: true,
92
+ source: :pr
93
+ }
94
+ else
95
+ record_error(bundle, "PR fetch failed for '#{pr_ref}': #{result[:error]}")
96
+ {range: pr_range_identifier(pr_ref), output: "Error: #{result[:error]}", success: false, error: result[:error], source: :pr}
97
+ end
98
+ rescue Ace::Git::Error => e
99
+ # Catches all ace-git errors: GitError, GhNotInstalledError, GhAuthenticationError,
100
+ # PrNotFoundError, TimeoutError (all inherit from Ace::Git::Error)
101
+ record_error(bundle, "PR fetch failed for '#{pr_ref}': #{e.message}")
102
+ {range: pr_range_identifier(pr_ref), output: "Error: #{e.message}", success: false, error: e.message, source: :pr}
103
+ rescue ArgumentError => e
104
+ record_error(bundle, "Invalid PR identifier '#{pr_ref}': #{e.message}")
105
+ nil
106
+ end
107
+
108
+ # Record error in bundle metadata
109
+ #
110
+ # @param bundle [Models::BundleData] Bundle to update
111
+ # @param message [String] Error message
112
+ def record_error(bundle, message)
113
+ bundle.metadata[:errors] ||= []
114
+ bundle.metadata[:errors] << message
115
+ end
116
+
117
+ # Generate standardized PR range identifier for error responses
118
+ # @param pr_ref [String] PR reference
119
+ # @return [String] Range identifier in "pr:ref" format
120
+ def pr_range_identifier(pr_ref)
121
+ "pr:#{pr_ref}"
122
+ end
123
+
124
+ # Surface errors to content for callers who don't inspect metadata
125
+ #
126
+ # @param bundle [Models::BundleData] Bundle to update
127
+ def surface_errors_to_content(bundle)
128
+ return unless bundle.metadata[:errors]&.any?
129
+
130
+ error_notice = bundle.metadata[:errors].map { |e| "- #{e}" }.join("\n")
131
+ bundle.content = "**PR Fetch Errors:**\n#{error_notice}\n\n" + (bundle.content || "")
132
+ end
133
+
134
+ # Add processed diffs to bundle's diffs section
135
+ #
136
+ # @param bundle [Models::BundleData] Bundle to update
137
+ # @param processed_diffs [Array<Hash>] Diff results to add
138
+ def add_diffs_to_bundle(bundle, processed_diffs)
139
+ bundle.sections ||= {}
140
+ bundle.sections["diffs"] ||= {title: "Diffs", _processed_diffs: []}
141
+ bundle.sections["diffs"][:_processed_diffs] ||= []
142
+ bundle.sections["diffs"][:_processed_diffs].concat(processed_diffs)
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ace
4
+ module Bundle
5
+ VERSION = "0.40.0"
6
+ end
7
+ end
data/lib/ace/bundle.rb ADDED
@@ -0,0 +1,251 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ace/support/config"
4
+ require "ace/core"
5
+ require "ace/git"
6
+ require_relative "bundle/version"
7
+
8
+ # Define error hierarchy before loading components (they reference these classes)
9
+ module Ace
10
+ module Bundle
11
+ # Base error class for all ace-bundle errors
12
+ class Error < StandardError; end
13
+
14
+ # Raised when section validation fails
15
+ class SectionValidationError < Error; end
16
+
17
+ # Raised when preset loading fails
18
+ class PresetLoadError < Error; end
19
+ end
20
+ end
21
+
22
+ # Main API
23
+ require_relative "bundle/organisms/bundle_loader"
24
+ require_relative "bundle/molecules/preset_manager"
25
+ require_relative "bundle/molecules/bundle_file_writer"
26
+
27
+ # CLI and commands
28
+ require_relative "bundle/cli"
29
+
30
+ module Ace
31
+ module Bundle
32
+ # Mutex for thread-safe config initialization
33
+ @config_mutex = Mutex.new
34
+
35
+ class << self
36
+ # Load bundle using preset
37
+ # @param preset_name [String] Name of the preset to load
38
+ # @param options [Hash] Additional options
39
+ # @return [Models::BundleData] Loaded bundle data
40
+ def load_preset(preset_name, options = {})
41
+ loader = Organisms::BundleLoader.new(options)
42
+ loader.load_preset(preset_name)
43
+ end
44
+
45
+ # Load multiple presets and merge them
46
+ # @param preset_names [Array<String>] Names of presets to load
47
+ # @param options [Hash] Additional options
48
+ # @return [Models::BundleData] Merged bundle data
49
+ def load_multiple_presets(preset_names, options = {})
50
+ loader = Organisms::BundleLoader.new(options)
51
+ loader.load_multiple_presets(preset_names)
52
+ end
53
+
54
+ # Inspect configuration of presets/files without loading files or executing commands
55
+ # @param inputs [Array<String>] Names of presets or paths to files to inspect
56
+ # @param options [Hash] Additional options
57
+ # @return [Models::BundleData] Configuration as YAML
58
+ def inspect_config(inputs, options = {})
59
+ loader = Organisms::BundleLoader.new(options)
60
+ loader.inspect_config(inputs)
61
+ end
62
+
63
+ # List available presets
64
+ # @return [Array<Hash>] List of available presets
65
+ def list_presets
66
+ manager = Molecules::PresetManager.new
67
+ manager.list_presets
68
+ end
69
+
70
+ # Load bundle from file
71
+ # @param path [String] Path to bundle file
72
+ # @param options [Hash] Additional options
73
+ # @return [Models::BundleData] Loaded bundle data
74
+ def load_file(path, options = {})
75
+ loader = Organisms::BundleLoader.new(options)
76
+ loader.load_file(path)
77
+ end
78
+
79
+ # Load with auto-detection
80
+ # @param input [String] File path, inline YAML, or preset name
81
+ # @param options [Hash] Additional options
82
+ # @return [Models::BundleData] Loaded bundle data
83
+ def load_auto(input, options = {})
84
+ loader = Organisms::BundleLoader.new(options)
85
+ loader.load_auto(input)
86
+ end
87
+
88
+ # Load multiple inputs and merge them
89
+ # @param inputs [Array<String>] Array of inputs to load
90
+ # @param options [Hash] Additional options
91
+ # @return [Models::BundleData] Merged bundle data
92
+ def load_multiple(inputs, options = {})
93
+ loader = Organisms::BundleLoader.new(options)
94
+ loader.load_multiple(inputs)
95
+ end
96
+
97
+ # Load multiple inputs (presets and files) and merge them
98
+ # @param preset_names [Array<String>] Names of presets to load
99
+ # @param file_paths [Array<String>] Paths to configuration files
100
+ # @param options [Hash] Additional options
101
+ # @return [Models::BundleData] Merged bundle data
102
+ def load_multiple_inputs(preset_names, file_paths, options = {})
103
+ loader = Organisms::BundleLoader.new(options)
104
+ loader.load_multiple_inputs(preset_names, file_paths, options)
105
+ end
106
+
107
+ # Write bundle output to file with optional chunking
108
+ # @param bundle [Models::BundleData] Bundle to write
109
+ # @param output_path [String] Output file path
110
+ # @param options [Hash] Additional options
111
+ # @return [Hash] Write result with success status
112
+ def write_output(bundle, output_path, options = {})
113
+ writer = Molecules::BundleFileWriter.new(
114
+ cache_dir: cache_dir,
115
+ max_lines: max_lines
116
+ )
117
+ writer.write_with_chunking(bundle, output_path, options)
118
+ end
119
+
120
+ # Get configuration for ace-bundle
121
+ # Follows ADR-022: Configuration Default and Override Pattern
122
+ # Uses Ace::Support::Config.create() for configuration cascade resolution
123
+ # Thread-safe: uses mutex for initialization
124
+ # @return [Hash] merged configuration hash
125
+ # @example Get current configuration
126
+ # config = Ace::Bundle.config
127
+ # puts config["cache_dir"] # => ".ace-local/bundle"
128
+ def config
129
+ # Fast path: return cached config if already initialized
130
+ return @config if defined?(@config) && @config
131
+
132
+ # Thread-safe initialization
133
+ @config_mutex.synchronize do
134
+ @config ||= load_config
135
+ end
136
+ end
137
+
138
+ # Reset configuration cache (mainly for testing)
139
+ # Thread-safe: uses mutex to prevent race conditions
140
+ def reset_config!
141
+ @config_mutex.synchronize do
142
+ @config = nil
143
+ end
144
+ end
145
+
146
+ # ---- Configuration Helper Methods (ADR-022 compliant) ----
147
+ # These read from config instead of using hardcoded constants
148
+
149
+ # Cache directory for bundle output files
150
+ # @return [String] Cache directory path (default: ".ace-local/bundle")
151
+ def cache_dir
152
+ config["cache_dir"] || ".ace-local/bundle"
153
+ end
154
+
155
+ # Maximum lines per chunk before splitting output into multiple files
156
+ # @return [Integer] Max lines per chunk (default: 2000)
157
+ def max_lines
158
+ config["max_lines"] || 2_000
159
+ end
160
+
161
+ # Line count threshold for auto-format output mode
162
+ # When no explicit --output mode is specified:
163
+ # - Content below this threshold: displayed inline (stdout)
164
+ # - Content at or above this threshold: saved to cache file
165
+ # @return [Integer] Auto-format threshold in lines (default: 500, range: 10-10000)
166
+ def auto_format_threshold
167
+ threshold = config["auto_format_threshold"]
168
+ # Ensure valid integer within reasonable bounds (10-10000 lines)
169
+ # - Below 10: too aggressive, would cache almost everything
170
+ # - Above 10000: defeats the purpose of auto-format
171
+ return 500 unless threshold.is_a?(Integer) && threshold.between?(10, 10_000)
172
+
173
+ threshold
174
+ end
175
+
176
+ # Compressor configuration section from global/project config
177
+ # @return [Hash] compressor config (default: {})
178
+ def compressor_config
179
+ config["compressor"] || {}
180
+ end
181
+
182
+ # Default compressor source scope from config
183
+ # @return [String] source scope (default: "off")
184
+ def compressor_source_scope
185
+ compressor_config["source_scope"] || "off"
186
+ end
187
+
188
+ # Default compressor mode from config
189
+ # @return [String] compressor mode (default: "exact")
190
+ def compressor_mode
191
+ compressor_config["mode"] || "exact"
192
+ end
193
+
194
+ private
195
+
196
+ # Load configuration using Ace::Support::Config cascade
197
+ # Resolves gem defaults from .ace-defaults/ and user overrides from .ace/
198
+ # @return [Hash] Merged and transformed configuration
199
+ def load_config
200
+ gem_root = Gem.loaded_specs["ace-bundle"]&.gem_dir ||
201
+ File.expand_path("../..", __dir__)
202
+
203
+ resolver = Ace::Support::Config.create(
204
+ config_dir: ".ace",
205
+ defaults_dir: ".ace-defaults",
206
+ gem_path: gem_root
207
+ )
208
+
209
+ # Resolve config for bundle namespace
210
+ config = resolver.resolve_namespace("bundle")
211
+
212
+ # Extract the bundle section for direct access
213
+ raw_config = config.data["bundle"] || config.data
214
+ normalize_keys(raw_config)
215
+ rescue Ace::Support::Config::YamlParseError => e
216
+ warn "ace-bundle: YAML syntax error in configuration"
217
+ warn " #{e.message}"
218
+ # Fall back to gem defaults
219
+ load_gem_defaults_fallback
220
+ rescue => e
221
+ warn "ace-bundle: Failed to load configuration: #{e.message}"
222
+ # Fall back to gem defaults
223
+ load_gem_defaults_fallback
224
+ end
225
+
226
+ # Load gem defaults directly as fallback when cascade resolution fails
227
+ # @return [Hash] Defaults hash or empty hash if defaults also fail
228
+ def load_gem_defaults_fallback
229
+ gem_root = Gem.loaded_specs["ace-bundle"]&.gem_dir ||
230
+ File.expand_path("../..", __dir__)
231
+ defaults_path = File.join(gem_root, ".ace-defaults", "bundle", "config.yml")
232
+
233
+ return {} unless File.exist?(defaults_path)
234
+
235
+ data = YAML.safe_load_file(defaults_path, permitted_classes: [Date], aliases: true) || {}
236
+ normalize_keys(data["bundle"] || data)
237
+ rescue
238
+ {} # Only return empty hash if even defaults fail to load
239
+ end
240
+
241
+ # Normalize hash keys to strings for consistent access
242
+ # @param hash [Hash] Hash with potentially mixed string/symbol keys
243
+ # @return [Hash] Hash with string keys
244
+ def normalize_keys(hash)
245
+ return {} unless hash.is_a?(Hash)
246
+
247
+ hash.transform_keys(&:to_s)
248
+ end
249
+ end
250
+ end
251
+ end
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ace-bundle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.40.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-config
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.7'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.7'
40
+ - !ruby/object:Gem::Dependency
41
+ name: ace-support-core
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.24'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.24'
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-git
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.11'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.11'
82
+ - !ruby/object:Gem::Dependency
83
+ name: ace-support-nav
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.18'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.18'
96
+ - !ruby/object:Gem::Dependency
97
+ name: ace-compressor
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '0.21'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.21'
110
+ description: Assembles files, shell commands, and git diffs into a single bundled
111
+ file. Configured via presets or markdown frontmatter with protocol URL support (wfi://,
112
+ guide://, tmpl://, prompt://, task://). Output to stdout or cache, with optional
113
+ compression through ace-compressor.
114
+ email:
115
+ - mc@cs3b.com
116
+ executables:
117
+ - ace-bundle
118
+ extensions: []
119
+ extra_rdoc_files: []
120
+ files:
121
+ - ".ace-defaults/bundle/config.yml"
122
+ - ".ace-defaults/bundle/presets/base.md"
123
+ - ".ace-defaults/bundle/presets/code-review.md"
124
+ - ".ace-defaults/bundle/presets/development.md"
125
+ - ".ace-defaults/bundle/presets/documentation-review.md"
126
+ - ".ace-defaults/bundle/presets/mixed-content-example.md"
127
+ - ".ace-defaults/bundle/presets/project-context.md"
128
+ - ".ace-defaults/bundle/presets/project.md"
129
+ - ".ace-defaults/bundle/presets/section-example-simple.md"
130
+ - ".ace-defaults/bundle/presets/security-review.md"
131
+ - ".ace-defaults/bundle/presets/simple-project.md"
132
+ - ".ace-defaults/bundle/presets/team.md"
133
+ - ".ace-defaults/nav/protocols/wfi-sources/ace-bundle.yml"
134
+ - CHANGELOG.md
135
+ - LICENSE
136
+ - README.md
137
+ - Rakefile
138
+ - exe/ace-bundle
139
+ - handbook/skills/as-bundle/SKILL.md
140
+ - handbook/skills/as-onboard/SKILL.md
141
+ - handbook/workflow-instructions/bundle.wf.md
142
+ - handbook/workflow-instructions/onboard.wf.md
143
+ - lib/ace/bundle.rb
144
+ - lib/ace/bundle/atoms/boundary_finder.rb
145
+ - lib/ace/bundle/atoms/bundle_normalizer.rb
146
+ - lib/ace/bundle/atoms/content_checker.rb
147
+ - lib/ace/bundle/atoms/line_counter.rb
148
+ - lib/ace/bundle/atoms/preset_list_formatter.rb
149
+ - lib/ace/bundle/atoms/preset_validator.rb
150
+ - lib/ace/bundle/atoms/section_validator.rb
151
+ - lib/ace/bundle/atoms/typo_detector.rb
152
+ - lib/ace/bundle/cli.rb
153
+ - lib/ace/bundle/cli/commands/load.rb
154
+ - lib/ace/bundle/models/bundle_data.rb
155
+ - lib/ace/bundle/molecules/bundle_chunker.rb
156
+ - lib/ace/bundle/molecules/bundle_file_writer.rb
157
+ - lib/ace/bundle/molecules/bundle_merger.rb
158
+ - lib/ace/bundle/molecules/preset_manager.rb
159
+ - lib/ace/bundle/molecules/section_compressor.rb
160
+ - lib/ace/bundle/molecules/section_formatter.rb
161
+ - lib/ace/bundle/molecules/section_processor.rb
162
+ - lib/ace/bundle/organisms/bundle_loader.rb
163
+ - lib/ace/bundle/organisms/pr_bundle_loader.rb
164
+ - lib/ace/bundle/version.rb
165
+ homepage: https://github.com/cs3b/ace
166
+ licenses:
167
+ - MIT
168
+ metadata:
169
+ allowed_push_host: https://rubygems.org
170
+ homepage_uri: https://github.com/cs3b/ace
171
+ source_code_uri: https://github.com/cs3b/ace
172
+ changelog_uri: https://github.com/cs3b/ace/blob/main/ace-bundle/CHANGELOG.md
173
+ rdoc_options: []
174
+ require_paths:
175
+ - lib
176
+ required_ruby_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: 3.2.0
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ requirements: []
187
+ rubygems_version: 3.6.9
188
+ specification_version: 4
189
+ summary: Assemble multiple sources into a single bundled file, with optional compression
190
+ test_files: []