ace-git-worktree 0.21.6 → 0.22.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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/docs/usage.md +37 -3
  4. data/handbook/skills/as-git-worktree-cleanup/SKILL.md +20 -0
  5. data/handbook/workflow-instructions/git/worktree-cleanup.wf.md +63 -0
  6. data/handbook/workflow-instructions/git/worktree-create.wf.md +6 -0
  7. data/lib/ace/git/worktree/cli/commands/bootstrap.rb +43 -0
  8. data/lib/ace/git/worktree/cli/commands/cleanup.rb +45 -0
  9. data/lib/ace/git/worktree/cli/commands/config.rb +27 -4
  10. data/lib/ace/git/worktree/cli/commands/create.rb +1 -0
  11. data/lib/ace/git/worktree/cli.rb +6 -0
  12. data/lib/ace/git/worktree/commands/bootstrap_command.rb +159 -0
  13. data/lib/ace/git/worktree/commands/cleanup_command.rb +307 -0
  14. data/lib/ace/git/worktree/commands/config_command.rb +354 -181
  15. data/lib/ace/git/worktree/commands/create_command.rb +5 -0
  16. data/lib/ace/git/worktree/models/worktree_config.rb +33 -3
  17. data/lib/ace/git/worktree/molecules/bootstrap_executor.rb +99 -0
  18. data/lib/ace/git/worktree/molecules/cleanup_applier.rb +225 -0
  19. data/lib/ace/git/worktree/molecules/cleanup_pr_resolver.rb +213 -0
  20. data/lib/ace/git/worktree/molecules/cleanup_reporter.rb +396 -0
  21. data/lib/ace/git/worktree/molecules/config_loader.rb +1 -1
  22. data/lib/ace/git/worktree/molecules/task_committer.rb +55 -8
  23. data/lib/ace/git/worktree/molecules/toolchain_truster.rb +112 -0
  24. data/lib/ace/git/worktree/molecules/worktree_lister.rb +17 -1
  25. data/lib/ace/git/worktree/organisms/task_worktree_orchestrator.rb +159 -10
  26. data/lib/ace/git/worktree/organisms/worktree_manager.rb +4 -2
  27. data/lib/ace/git/worktree/version.rb +1 -1
  28. metadata +23 -12
@@ -1,4 +1,9 @@
1
- # frozen_string_literal: true
1
+ require "json"
2
+ require "yaml"
3
+ require "fileutils"
4
+ require_relative "../organisms/worktree_manager"
5
+ require_relative "../molecules/config_loader"
6
+ require_relative "../models/worktree_config"
2
7
 
3
8
  module Ace
4
9
  module Git
@@ -6,14 +11,8 @@ module Ace
6
11
  module Commands
7
12
  # Config command
8
13
  #
9
- # Displays and validates worktree configuration.
10
- # Shows current settings, configuration file locations, and validation results.
11
- #
12
- # @example Show current configuration
13
- # ConfigCommand.new.run(["--show"])
14
- #
15
- # @example Validate configuration
16
- # ConfigCommand.new.run(["--validate"])
14
+ # Displays, initializes, updates, and validates worktree configuration.
15
+ # Shows current settings, provenance tracking, and validation results.
17
16
  class ConfigCommand
18
17
  # Initialize a new ConfigCommand
19
18
  def initialize
@@ -28,31 +27,34 @@ module Ace
28
27
  options = parse_arguments(args)
29
28
  return show_help if options[:help]
30
29
 
30
+ if options[:init]
31
+ return init_project_config
32
+ end
33
+
34
+ if options[:set_bootstrap]
35
+ return set_bootstrap_config(options)
36
+ end
37
+
31
38
  # Default to showing configuration if no action specified
32
39
  options[:show] = true unless options[:validate] || options[:show] || options[:files]
33
40
 
34
- validate_options(options)
35
-
36
41
  results = []
37
42
 
38
43
  if options[:show]
39
- results << show_configuration
44
+ results << show_configuration(json: options[:json])
40
45
  end
41
46
 
42
47
  if options[:validate]
43
- results << validate_configuration
48
+ results << validate_configuration(bootstrap_only: options[:bootstrap], json: options[:json])
44
49
  end
45
50
 
46
51
  if options[:files]
47
52
  results << show_configuration_files
48
53
  end
49
54
 
50
- # Return success if all operations succeeded
51
55
  (results.all? { |result| result == 0 }) ? 0 : 1
52
56
  rescue ArgumentError => e
53
57
  puts "Error: #{e.message}"
54
- puts
55
- show_help
56
58
  1
57
59
  rescue => e
58
60
  puts "Error: #{e.message}"
@@ -67,51 +69,31 @@ module Ace
67
69
  ace-git-worktree config - Manage worktree configuration
68
70
 
69
71
  USAGE:
70
- ace-git-worktree config [OPTIONS]
72
+ ace-git-worktree config [SUBCOMMAND / OPTIONS]
71
73
 
72
74
  ACTIONS:
73
- --show Show current configuration (default)
74
- --validate Validate configuration
75
- --files Show configuration file locations
76
-
77
- OPTIONS:
78
- --verbose, -v Show detailed information
79
- --help, -h Show this help message
75
+ init Initialize minimal project worktree configuration
76
+ set-bootstrap Set bootstrap command policy
77
+ --show Show current configuration (default)
78
+ --validate Validate configuration
79
+ --files Show configuration file locations
80
+
81
+ SET BOOTSTRAP OPTIONS:
82
+ --command <cmd> Command to run
83
+ --working-dir <path> Working directory relative to project root
84
+ --timeout <sec> Timeout in seconds (max 300)
85
+ --required | --advisory Policy for execution failure
86
+ --env KEY=VALUE Environment variables
87
+
88
+ FORMAT OPTIONS:
89
+ --json Format output as JSON
90
+ --bootstrap Validate bootstrap section only
80
91
 
81
92
  EXAMPLES:
82
- # Show current configuration
83
- ace-git-worktree config
84
- ace-git-worktree config --show
85
-
86
- # Validate configuration
87
- ace-git-worktree config --validate
88
-
89
- # Show configuration file locations
90
- ace-git-worktree config --files
91
-
92
- # Show everything
93
- ace-git-worktree config --show --validate --files
94
-
95
- CONFIGURATION FILES:
96
- .ace/git/worktree.yml Project-specific configuration
97
- .ace-defaults/git/worktree.yml Example configuration template
98
- ~/.ace/git/worktree.yml User-specific configuration
99
-
100
- CONFIGURATION OPTIONS:
101
- git.worktree.root_path Worktree root directory
102
- git.worktree.mise_trust_auto Automatic mise trust
103
- git.worktree.task.* Task-related settings
104
- git.worktree.cleanup.* Cleanup behavior settings
105
-
106
- VALIDATION:
107
- Checks for:
108
- • Valid configuration structure
109
- • Required configuration fields
110
- • Accessible worktree root directory
111
- • Valid template variables
112
- • Consistent settings
113
-
114
- For configuration examples, see .ace-defaults/git/worktree.yml
93
+ ace-git-worktree config init
94
+ ace-git-worktree config set-bootstrap --command "npm install" --timeout 120 --required
95
+ ace-git-worktree config show --json
96
+ ace-git-worktree config validate --bootstrap --json
115
97
  HELP
116
98
  0
117
99
  end
@@ -127,6 +109,16 @@ module Ace
127
109
  show: false,
128
110
  validate: false,
129
111
  files: false,
112
+ init: false,
113
+ set_bootstrap: false,
114
+ json: false,
115
+ bootstrap: false,
116
+ command: nil,
117
+ working_dir: nil,
118
+ timeout: nil,
119
+ required: false,
120
+ advisory: false,
121
+ env: [],
130
122
  verbose: false,
131
123
  help: false
132
124
  }
@@ -136,12 +128,36 @@ module Ace
136
128
  arg = args[i]
137
129
 
138
130
  case arg
139
- when "--show"
131
+ when "init"
132
+ options[:init] = true
133
+ when "set-bootstrap"
134
+ options[:set_bootstrap] = true
135
+ when "show", "--show"
140
136
  options[:show] = true
141
- when "--validate"
137
+ when "validate", "--validate"
142
138
  options[:validate] = true
143
- when "--files"
139
+ when "files", "--files"
144
140
  options[:files] = true
141
+ when "--json"
142
+ options[:json] = true
143
+ when "--bootstrap"
144
+ options[:bootstrap] = true
145
+ when "--command"
146
+ i += 1
147
+ options[:command] = args[i]
148
+ when "--working-dir"
149
+ i += 1
150
+ options[:working_dir] = args[i]
151
+ when "--timeout"
152
+ i += 1
153
+ options[:timeout] = args[i]
154
+ when "--required"
155
+ options[:required] = true
156
+ when "--advisory"
157
+ options[:advisory] = true
158
+ when "--env"
159
+ i += 1
160
+ options[:env] << args[i] if args[i]
145
161
  when "--verbose", "-v"
146
162
  options[:verbose] = true
147
163
  when "--help", "-h"
@@ -149,15 +165,7 @@ module Ace
149
165
  when /^--/
150
166
  raise ArgumentError, "Unknown option: #{arg}"
151
167
  else
152
- # Accept subcommand arguments (show, validate) as aliases for flags
153
- case arg
154
- when "show"
155
- options[:show] = true
156
- when "validate"
157
- options[:validate] = true
158
- else
159
- raise ArgumentError, "Unexpected argument: #{arg}"
160
- end
168
+ raise ArgumentError, "Unexpected argument: #{arg}"
161
169
  end
162
170
 
163
171
  i += 1
@@ -166,29 +174,150 @@ module Ace
166
174
  options
167
175
  end
168
176
 
169
- # Validate parsed options
177
+ # Initialize minimal project override configuration
178
+ #
179
+ # @return [Integer] Exit code
180
+ def init_project_config
181
+ project_root = Dir.pwd
182
+ ace_dir = File.join(project_root, ".ace", "git")
183
+ FileUtils.mkdir_p(ace_dir)
184
+ config_file = File.join(ace_dir, "worktree.yml")
185
+
186
+ if File.exist?(config_file)
187
+ begin
188
+ existing = YAML.safe_load_file(config_file, permitted_classes: [Date], aliases: true)
189
+ if existing && !existing.is_a?(Hash)
190
+ puts "Error: Incompatible existing project configuration at #{config_file}"
191
+ return 1
192
+ end
193
+ rescue => e
194
+ puts "Error: Incompatible existing project configuration at #{config_file}: #{e.message}"
195
+ return 1
196
+ end
197
+ puts "Project configuration already initialized at #{config_file}"
198
+ return 0
199
+ end
200
+
201
+ minimal = <<~YAML
202
+ # ACE Git Worktree Project Configuration
203
+ git:
204
+ worktree: {}
205
+ YAML
206
+
207
+ tmp_file = "#{config_file}.tmp.#{Process.pid}"
208
+ File.write(tmp_file, minimal)
209
+ File.rename(tmp_file, config_file)
210
+ puts "Initialized project worktree configuration at #{config_file}"
211
+ 0
212
+ end
213
+
214
+ # Set bootstrap policy configuration
170
215
  #
171
- # @param options [Hash] Parsed options
172
- def validate_options(options)
173
- # No specific validation needed for config command
216
+ # @param options [Hash] Options with command, working_dir, timeout, required/advisory, env
217
+ # @return [Integer] Exit code
218
+ def set_bootstrap_config(options)
219
+ command = options[:command]
220
+ if command.nil? || command.strip.empty?
221
+ puts "Error: --command is required for set-bootstrap"
222
+ return 1
223
+ end
224
+
225
+ working_dir = options[:working_dir] || "."
226
+ if working_dir.start_with?("/") || working_dir.include?("..")
227
+ puts "Error: --working-dir must be a relative path within the project root"
228
+ return 1
229
+ end
230
+
231
+ timeout = (options[:timeout] || 60).to_i
232
+ if timeout <= 0 || timeout > 300
233
+ puts "Error: --timeout must be a positive integer <= 300"
234
+ return 1
235
+ end
236
+
237
+ if options[:required] && options[:advisory]
238
+ puts "Error: Cannot specify both --required and --advisory"
239
+ return 1
240
+ end
241
+
242
+ policy = options[:advisory] ? "advisory" : "required"
243
+
244
+ env_hash = {}
245
+ Array(options[:env]).each do |pair|
246
+ unless pair.include?("=")
247
+ puts "Error: Environment variables must be in KEY=VALUE format: #{pair}"
248
+ return 1
249
+ end
250
+ k, v = pair.split("=", 2)
251
+ env_hash[k.strip] = v.to_s
252
+ end
253
+
254
+ project_root = Dir.pwd
255
+ ace_dir = File.join(project_root, ".ace", "git")
256
+ FileUtils.mkdir_p(ace_dir)
257
+ config_file = File.join(ace_dir, "worktree.yml")
258
+
259
+ existing_yaml = {}
260
+ if File.exist?(config_file)
261
+ begin
262
+ loaded = YAML.safe_load_file(config_file, permitted_classes: [Date], aliases: true)
263
+ existing_yaml = loaded if loaded.is_a?(Hash)
264
+ rescue => e
265
+ puts "Error reading existing configuration: #{e.message}"
266
+ return 1
267
+ end
268
+ end
269
+
270
+ existing_yaml["git"] ||= {}
271
+ existing_yaml["git"]["worktree"] ||= {}
272
+ existing_yaml["git"]["worktree"]["bootstrap"] = {
273
+ "command" => command,
274
+ "working_dir" => working_dir,
275
+ "timeout" => timeout,
276
+ "policy" => policy,
277
+ "env" => env_hash
278
+ }
279
+
280
+ tmp_file = "#{config_file}.tmp.#{Process.pid}"
281
+ File.write(tmp_file, YAML.dump(existing_yaml))
282
+ File.rename(tmp_file, config_file)
283
+ puts "Updated bootstrap policy at #{config_file}"
284
+ 0
174
285
  end
175
286
 
176
- # Show current configuration
287
+ # Show current configuration (text or JSON format)
177
288
  #
289
+ # @param json [Boolean] Format as JSON
178
290
  # @return [Integer] Exit code
179
- def show_configuration
291
+ def show_configuration(json: false)
292
+ if json
293
+ json_data = build_show_json
294
+ puts JSON.pretty_generate(json_data)
295
+ return 0
296
+ end
297
+
180
298
  puts "Current Worktree Configuration:"
181
299
  puts "=" * 50
182
300
 
183
301
  config = @manager.configuration
184
302
 
185
- # Basic settings
186
303
  puts "Root Path: #{config.root_path}"
187
304
  puts "Absolute Root: #{config.absolute_root_path}"
188
305
  puts "Mise Trust Auto: #{config.mise_trust_auto? ? "enabled" : "disabled"}"
189
306
  puts
190
307
 
191
- # Task settings
308
+ if config.bootstrap_configured?
309
+ bs = config.bootstrap
310
+ puts "Bootstrap Settings:"
311
+ puts " Command: #{bs["command"]}"
312
+ puts " Working Dir: #{bs["working_dir"] || "."}"
313
+ puts " Timeout: #{bs["timeout"]}s"
314
+ puts " Policy: #{bs["policy"] || "required"}"
315
+ puts
316
+ else
317
+ puts "Bootstrap Settings: not configured"
318
+ puts
319
+ end
320
+
192
321
  puts "Task Settings:"
193
322
  puts " Directory Format: #{config.directory_format}"
194
323
  puts " Branch Format: #{config.branch_format}"
@@ -197,33 +326,6 @@ module Ace
197
326
  puts " Add Worktree Metadata: #{config.add_worktree_metadata? ? "enabled" : "disabled"}"
198
327
  puts
199
328
 
200
- if config.auto_commit_task?
201
- puts "Commit Message Format:"
202
- puts " #{config.commit_message_format}"
203
- puts
204
- end
205
-
206
- # Cleanup settings
207
- puts "Cleanup Settings:"
208
- puts " On Merge: #{config.cleanup_on_merge? ? "enabled" : "disabled"}"
209
- puts " On Delete: #{config.cleanup_on_delete? ? "enabled" : "disabled"}"
210
- puts
211
-
212
- # Template variables
213
- puts "Available Template Variables:"
214
- puts " {id} - Task numeric ID (e.g., 081)"
215
- puts " {task_id} - Full task ID (e.g., task.081)"
216
- puts " {slug} - URL-safe slug from task title"
217
- puts
218
-
219
- # Example usage
220
- puts "Example Usage:"
221
- task_id = "081"
222
- task_slug = "fix-authentication-bug"
223
- puts " Directory: #{config.directory_format.gsub("{id}", task_id).gsub("{slug}", task_slug)}"
224
- puts " Branch: #{config.branch_format.gsub("{id}", task_id).gsub("{slug}", task_slug)}"
225
- puts
226
-
227
329
  0
228
330
  rescue => e
229
331
  puts "Error showing configuration: #{e.message}"
@@ -232,47 +334,169 @@ module Ace
232
334
 
233
335
  # Validate configuration
234
336
  #
235
- # @return [Integer] Exit code
236
- def validate_configuration
237
- puts "Configuration Validation:"
238
- puts "=" * 30
337
+ # @param bootstrap_only [Boolean] Validate bootstrap section only
338
+ # @param json [Boolean] Output JSON format
339
+ def validate_configuration(bootstrap_only: false, json: false)
340
+ result = @manager.validate_configuration rescue nil
341
+ loader = Molecules::ConfigLoader.new(Dir.pwd)
342
+ config = loader.load_without_validation rescue nil
343
+ result ||= (config ? {success: config.validate.empty?, errors: config.validate} : {success: true, valid: true, errors: []})
344
+ errors = bootstrap_only ? [] : (result[:errors] || []).dup
345
+
346
+ if bootstrap_only || (config && config.bootstrap_configured?)
347
+ bs = config ? config.bootstrap : {}
348
+ if !config || !config.bootstrap_configured?
349
+ errors << "Bootstrap is not configured" if bootstrap_only
350
+ else
351
+ cmd = bs["command"]
352
+ errors << "Bootstrap command must be a non-empty string" if cmd.nil? || cmd.to_s.strip.empty?
239
353
 
240
- result = @manager.validate_configuration
354
+ wdir = bs["working_dir"] || "."
355
+ errors << "Bootstrap working_dir must be a relative path without leading slash or .." if wdir.start_with?("/") || wdir.include?("..")
241
356
 
242
- if result[:success]
243
- puts " Configuration is valid"
244
- puts
357
+ timeout = bs["timeout"].to_i
358
+ errors << "Bootstrap timeout must be > 0 and <= 300" if timeout <= 0 || timeout > 300
245
359
 
246
- if result[:errors].any?
247
- puts "Warnings:"
248
- result[:errors].each { |error| puts " ⚠️ #{error}" }
360
+ policy = bs["policy"] || "required"
361
+ errors << "Bootstrap policy must be 'required' or 'advisory'" unless %w[required advisory].include?(policy)
249
362
  end
250
- else
251
- puts "❌ Configuration validation failed"
252
- puts
253
- puts "Errors:"
254
- result[:errors].each { |error| puts " ❌ #{error}" }
255
- puts
363
+ end
256
364
 
257
- puts "Suggestions:"
258
- puts " • Check .ace/git/worktree.yml for syntax errors"
259
- puts " • Ensure all required fields are present"
260
- puts " • Verify template variables are correct"
261
- puts " • Check that worktree root directory is accessible"
262
- puts " • See .ace-defaults/git/worktree.yml for examples"
263
- puts
365
+ valid = errors.empty? && (bootstrap_only || result[:success] != false)
366
+
367
+ if json
368
+ json_result = {
369
+ schema_version: "1.0",
370
+ valid: valid,
371
+ mode: bootstrap_only ? "bootstrap_only" : "full",
372
+ errors: errors
373
+ }
374
+ puts JSON.pretty_generate(json_result)
375
+ return valid ? 0 : 1
376
+ end
377
+
378
+ puts "Configuration Validation:"
379
+ puts "=" * 30
264
380
 
381
+ if valid
382
+ puts "✅ Configuration is valid"
383
+ else
384
+ puts "❌ Configuration validation failed"
385
+ errors.each { |err| puts " ❌ #{err}" }
265
386
  return 1
266
387
  end
267
388
 
268
- puts
269
-
270
389
  0
271
390
  rescue => e
272
391
  puts "Error validating configuration: #{e.message}"
273
392
  1
274
393
  end
275
394
 
395
+ # Safely load YAML file
396
+ def load_yaml_file(path)
397
+ return {} unless File.exist?(path)
398
+ YAML.safe_load_file(path, aliases: true)
399
+ rescue
400
+ begin
401
+ YAML.load_file(path) || {}
402
+ rescue
403
+ {}
404
+ end
405
+ end
406
+
407
+ # Build JSON representation of configuration and provenance
408
+ #
409
+ # @return [Hash] JSON structure
410
+ def build_show_json
411
+ loader = Molecules::ConfigLoader.new(Dir.pwd)
412
+ config = loader.load_without_validation
413
+ project_root = Dir.pwd
414
+
415
+ proj_file = File.join(project_root, ".ace", "git", "worktree.yml")
416
+ user_file = File.expand_path("~/.ace/git/worktree.yml")
417
+ pkg_file = File.join(project_root, ".ace-defaults", "git", "worktree.yml")
418
+
419
+ proj_data = load_yaml_file(proj_file)
420
+ user_data = load_yaml_file(user_file)
421
+
422
+ provenance_for = lambda do |*keys|
423
+ has_proj = proj_data.is_a?(Hash) && !proj_data.dig("git", "worktree", *keys).nil?
424
+ has_user = user_data.is_a?(Hash) && !user_data.dig("git", "worktree", *keys).nil?
425
+
426
+ if has_proj
427
+ "project"
428
+ elsif has_user
429
+ "user"
430
+ else
431
+ "package_default"
432
+ end
433
+ end
434
+
435
+ redact_env = lambda do |env_h|
436
+ return {} unless env_h.is_a?(Hash)
437
+ env_h.each_with_object({}) do |(k, v), acc|
438
+ if k.to_s.match?(/(secret|token|key|pass|auth|credential)/i)
439
+ acc[k.to_s] = "[REDACTED]"
440
+ else
441
+ acc[k.to_s] = v.to_s
442
+ end
443
+ end
444
+ end
445
+
446
+ bootstrap_h = config.bootstrap
447
+ if config.bootstrap_configured?
448
+ effective_bootstrap = {
449
+ "command" => bootstrap_h["command"],
450
+ "working_dir" => bootstrap_h["working_dir"] || ".",
451
+ "timeout" => (bootstrap_h["timeout"] || 60).to_i,
452
+ "policy" => bootstrap_h["policy"] || "required",
453
+ "env" => redact_env.call(bootstrap_h["env"])
454
+ }
455
+ else
456
+ effective_bootstrap = "not_configured"
457
+ end
458
+
459
+ provenance = {
460
+ "root_path" => provenance_for.call("root_path"),
461
+ "auto_navigate" => provenance_for.call("auto_navigate"),
462
+ "tmux" => provenance_for.call("tmux"),
463
+ "mise_trust_auto" => provenance_for.call("mise_trust_auto")
464
+ }
465
+
466
+ if config.bootstrap_configured?
467
+ provenance["bootstrap.command"] = provenance_for.call("bootstrap", "command")
468
+ provenance["bootstrap.working_dir"] = provenance_for.call("bootstrap", "working_dir")
469
+ provenance["bootstrap.timeout"] = provenance_for.call("bootstrap", "timeout")
470
+ provenance["bootstrap.policy"] = provenance_for.call("bootstrap", "policy")
471
+ if bootstrap_h["env"].is_a?(Hash)
472
+ bootstrap_h["env"].each_key do |ek|
473
+ provenance["bootstrap.env.#{ek}"] = provenance_for.call("bootstrap", "env", ek)
474
+ end
475
+ end
476
+ end
477
+
478
+ validation_errors = config.validate
479
+ {
480
+ schema_version: "1.0",
481
+ config_files: [
482
+ {path: proj_file, exists: File.exist?(proj_file), type: "project"},
483
+ {path: user_file, exists: File.exist?(user_file), type: "user"},
484
+ {path: pkg_file, exists: File.exist?(pkg_file), type: "package"}
485
+ ],
486
+ effective: {
487
+ root_path: config.root_path,
488
+ auto_navigate: config.auto_navigate?,
489
+ mise_trust_auto: config.mise_trust_auto?,
490
+ bootstrap: effective_bootstrap
491
+ },
492
+ provenance: provenance,
493
+ validation: {
494
+ valid: validation_errors.empty?,
495
+ errors: validation_errors
496
+ }
497
+ }
498
+ end
499
+
276
500
  # Show configuration file locations
277
501
  #
278
502
  # @return [Integer] Exit code
@@ -280,69 +504,18 @@ module Ace
280
504
  puts "Configuration Files:"
281
505
  puts "=" * 20
282
506
 
283
- # Get configuration files from config loader
284
507
  config_loader = @manager.instance_variable_get(:@config_loader)
285
508
  config_files = config_loader.config_files
286
509
 
287
510
  config_files.each do |file|
288
511
  if File.exist?(file)
289
512
  puts "✅ #{file} (exists)"
290
-
291
- # Show some info about the file
292
- begin
293
- stat = File.stat(file)
294
- size = stat.size
295
- mtime = stat.mtime.strftime("%Y-%m-%d %H:%M:%S")
296
- puts " Size: #{format_bytes(size)}"
297
- puts " Modified: #{mtime}"
298
-
299
- # Check if it's the active config
300
- if file.include?(".ace/git/worktree.yml")
301
- puts " 📍 Active project configuration"
302
- elsif file.include?(".ace-defaults/")
303
- puts " 📋 Example template"
304
- elsif file.include?("~/.ace/")
305
- puts " 👤 User configuration"
306
- end
307
- rescue => e
308
- puts " ⚠️ Error reading file info: #{e.message}"
309
- end
310
513
  else
311
514
  puts "❌ #{file} (not found)"
312
515
  end
313
- puts
314
516
  end
315
517
 
316
- # Show configuration cascade order
317
- puts "Configuration Priority (highest to lowest):"
318
- puts " 1. .ace/git/worktree.yml (project-specific)"
319
- puts " 2. ~/.ace/git/worktree.yml (user-specific)"
320
- puts " 3. .ace-defaults/git/worktree.yml (defaults)"
321
- puts
322
- puts "Note: Later configurations override earlier ones."
323
- puts
324
-
325
518
  0
326
- rescue => e
327
- puts "Error showing configuration files: #{e.message}"
328
- 1
329
- end
330
-
331
- # Format bytes in human readable format
332
- #
333
- # @param bytes [Integer] Number of bytes
334
- # @return [String] Formatted string
335
- def format_bytes(bytes)
336
- units = %w[B KB MB GB]
337
- size = bytes.to_f
338
- unit_index = 0
339
-
340
- while size >= 1024 && unit_index < units.length - 1
341
- size /= 1024
342
- unit_index += 1
343
- end
344
-
345
- "#{size.round(1)} #{units[unit_index]}"
346
519
  end
347
520
  end
348
521
  end