ace-support-config 0.10.2 → 0.11.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16e2e0c5255bb10848420c2985d022bdd807e268e8221131fda820d132539d9a
4
- data.tar.gz: adebbb9e9f34fb1bb04d6afd408bf2bcff4d64a18634198051f911e57014e623
3
+ metadata.gz: 33ca9302021e76335a714f27321b3075dd172056154ed5d1769b6f7b9ea7d6c7
4
+ data.tar.gz: e06462886d8d07fa3104367a96d129957b8554b8ac4419651f51c220dcd09167
5
5
  SHA512:
6
- metadata.gz: bf334d64a77eb96a0286b77be99ef38567adda7d0fe93044aa8341eabf5da36465b5bfbf5c2341eb4e07fdab134bfda06c2d1ea998547daf2b5fba17d35d21e2
7
- data.tar.gz: 4ee061b82ac2011c8dcd217c747659baad216cbf615f31c9b8a1883c14f89748a87f9b2e747eec52387367678e85e4ed67c4b08962bd72ad04f77f60a298c822
6
+ metadata.gz: 5f6377fe1c334cdf394a619c0548966317167789dd3214c87d7cbef778fe069d7e059af7db77d53fcc86aeb0acb445ef4eb644cbfb29e1f2006f73f74aa671ef
7
+ data.tar.gz: d21e340eb555a7457aabcf55e7ea26120b54b9ed282f7227658810377274501e5fac8ce1b1d0519f8a9868330502a8d0dbae4e2b69afd8805f8b37ac033de699
data/CHANGELOG.md CHANGED
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.11.2] - 2026-04-13
11
+
12
+ ### Fixed
13
+ - Made bootstrap `.gitignore` detection line-aware so commented or negated `.ace-local/` mentions no longer suppress appending the real ignore rule.
14
+
15
+ ### Technical
16
+ - Added regression coverage for commented and negated `.gitignore` mentions during bootstrap merges.
17
+
18
+ ## [0.11.1] - 2026-04-13
19
+
20
+ ### Fixed
21
+ - Preserve existing `.gitignore` rules even when `ace-config init --force` refreshes bootstrap files.
22
+ - Anchor project-root bootstrap files (`.gitignore`, `AGENTS.md`, `CLAUDE.md`) to the detected repository root so subdirectory runs do not seed them into the wrong location.
23
+
24
+ ## [0.11.0] - 2026-04-13
25
+
26
+ ### Changed
27
+ - **ace-support-config v0.11.0**: Taught `ace-config init` to bootstrap project-root guidance files, include dotfile defaults, and append `.ace-local/` to existing `.gitignore` files without overwriting user-owned `AGENTS.md` or `CLAUDE.md`.
28
+
29
+ ## [0.10.4] - 2026-04-13
30
+
31
+ ### Changed
32
+ - **ace-support-config v0.10.4**: Standardized shared package tests to the fast-only layout and updated testing flow defaults.
33
+
34
+
35
+ ## [0.10.3] - 2026-04-11
36
+
37
+ ### Technical
38
+ - Migrated package tests to the `fast`/`feat` layout by moving deterministic ATOM coverage to `test/fast/` and former `test/integration/` suites to `test/feat/`.
39
+ - Updated package docs to publish the `ace-test ace-support-config` (`fast`), `feat`, and `all` contract and keep package scope deterministic-only.
40
+
10
41
  ## [0.10.2] - 2026-03-31
11
42
 
12
43
  ### Technical
data/README.md CHANGED
@@ -29,6 +29,18 @@ ace-config version
29
29
  ace-config help
30
30
  ```
31
31
 
32
+ ## Testing
33
+
34
+ `ace-support-config` uses the ACE deterministic test taxonomy:
35
+
36
+ ```bash
37
+ ace-test ace-support-config # fast (default)
38
+ ace-test ace-support-config feat # deterministic feature coverage
39
+ ace-test ace-support-config all # fast + feat
40
+ ```
41
+
42
+ This package does not define a package-owned `e2e` layer in this migration.
43
+
32
44
  ## How It Works
33
45
 
34
46
  1. A resolver builds a configuration cascade from the nearest `.ace` directory up to user-home and gem-default layers.
@@ -0,0 +1,29 @@
1
+ ---
2
+ description: Showcase ace-config init bootstrapping project-root guidance files from a subdirectory
3
+ tags:
4
+ - ace-config
5
+ - ace-support-config
6
+ - bootstrap
7
+ settings:
8
+ font_size: 16
9
+ width: 1200
10
+ height: 700
11
+ format: gif
12
+ scenes:
13
+ - name: Initialize config from a nested working directory
14
+ commands:
15
+ - type: mkdir -p repo/subdir && cd repo && git init
16
+ sleep: 3s
17
+ - type: cd subdir && ace-config init support-core
18
+ sleep: 5s
19
+ - name: Verify bootstrap files landed at the repository root
20
+ commands:
21
+ - type: cd ../ && find . -maxdepth 2 \\( -name '.gitignore' -o -name 'AGENTS.md' -o -name 'CLAUDE.md' \\) | sort
22
+ sleep: 4s
23
+ - type: printf '\n.gitignore contents:\n' && cat .gitignore
24
+ sleep: 4s
25
+ setup:
26
+ - sandbox
27
+ - copy-fixtures
28
+ teardown:
29
+ - cleanup
data/docs/usage.md CHANGED
@@ -25,6 +25,21 @@ ace-config version
25
25
  ace-config help
26
26
  ```
27
27
 
28
+ ## Testing Contract
29
+
30
+ `ace-support-config` follows the ACE deterministic package targets:
31
+
32
+ ```bash
33
+ ace-test ace-support-config
34
+ ace-test ace-support-config feat
35
+ ace-test ace-support-config all
36
+ ```
37
+
38
+ - `fast` (default) runs isolated deterministic package tests under `test/fast/`.
39
+ - `feat` runs deterministic feature tests under `test/feat/`.
40
+ - `all` runs `fast` then `feat`.
41
+ - This package does not publish a package-owned `e2e` target in this migration.
42
+
28
43
  ### Cascade Priority (highest to lowest)
29
44
 
30
45
  1. **Project level** - `<project_root>/.ace/`
@@ -197,4 +212,4 @@ Ace::Support::Config.reset_config!
197
212
  This clears:
198
213
  - Project root cache
199
214
  - Thread-local test mode state
200
- - Thread-local mock data
215
+ - Thread-local mock data
@@ -21,7 +21,7 @@ module Ace
21
21
  class ProjectConfigScanner
22
22
  # Directories to skip during traversal
23
23
  SKIP_DIRS = %w[.git .cache vendor node_modules tmp coverage
24
- .bundle _legacy .ace-local .ace-tasks .ace-taskflow].freeze
24
+ .bundle _legacy .ace-local .ace-tasks .ace-task].freeze
25
25
 
26
26
  # @param project_root [String, nil] Root directory to scan (default: Dir.pwd)
27
27
  # @param config_dir [String] Config folder name (default: ".ace")
@@ -9,6 +9,9 @@ module Ace
9
9
  module Config
10
10
  module Organisms
11
11
  class ConfigInitializer
12
+ PROJECT_ROOT_DIR = "project-root"
13
+ GITIGNORE_ACE_LOCAL_ENTRY = ".ace-local/"
14
+
12
15
  def initialize(force: false, dry_run: false, global: false, verbose: false)
13
16
  @force = force
14
17
  @dry_run = dry_run
@@ -57,7 +60,9 @@ module Ace
57
60
  end
58
61
 
59
62
  def target_directory
60
- @global ? File.expand_path("~/.ace") : ".ace"
63
+ return File.expand_path("~/.ace") if @global
64
+
65
+ File.join(project_root, ".ace")
61
66
  end
62
67
 
63
68
  def show_config_docs_if_needed(gem_name, target_dir)
@@ -71,17 +76,27 @@ module Ace
71
76
  end
72
77
 
73
78
  def copy_config_files(source_dir, target_dir)
74
- Dir.glob("#{source_dir}/**/*").each do |source_file|
79
+ glob_pattern = File.join(source_dir, "**", "*")
80
+
81
+ Dir.glob(glob_pattern, File::FNM_DOTMATCH).each do |source_file|
82
+ basename = File.basename(source_file)
83
+ next if basename == "." || basename == ".."
75
84
  next if File.directory?(source_file)
76
85
 
77
86
  relative_path = Pathname.new(source_file).relative_path_from(Pathname.new(source_dir))
78
- target_file = File.join(target_dir, relative_path.to_s)
87
+ target_file = target_file_for(relative_path, target_dir)
88
+ next unless target_file
79
89
 
80
90
  copy_file(source_file, target_file)
81
91
  end
82
92
  end
83
93
 
84
94
  def copy_file(source, target)
95
+ if File.basename(target) == ".gitignore"
96
+ merge_gitignore(source, target)
97
+ return
98
+ end
99
+
85
100
  if File.exist?(target) && !@force
86
101
  @skipped_files << target
87
102
  puts " Skipped: #{target} (already exists)" if @verbose
@@ -98,6 +113,72 @@ module Ace
98
113
  end
99
114
  end
100
115
 
116
+ def target_file_for(relative_path, target_dir)
117
+ relative_str = relative_path.to_s
118
+
119
+ if relative_str.start_with?("#{PROJECT_ROOT_DIR}/")
120
+ return nil if @global
121
+
122
+ return File.join(project_root, relative_str.delete_prefix("#{PROJECT_ROOT_DIR}/"))
123
+ end
124
+
125
+ File.join(target_dir, relative_str)
126
+ end
127
+
128
+ def merge_gitignore(source, target)
129
+ target_exists = File.exist?(target)
130
+
131
+ if target_exists
132
+ merge_gitignore_entry_if_missing(source, target)
133
+ return
134
+ end
135
+
136
+ if @dry_run
137
+ puts " Would copy: #{source} -> #{target}"
138
+ else
139
+ FileUtils.mkdir_p(File.dirname(target))
140
+ FileUtils.cp(source, target)
141
+ @copied_files << target
142
+ puts " Copied: #{target}" if @verbose
143
+ end
144
+ end
145
+
146
+ def merge_gitignore_entry_if_missing(source, target)
147
+ existing_content = File.read(target)
148
+ return if gitignore_entry_present?(existing_content, GITIGNORE_ACE_LOCAL_ENTRY)
149
+
150
+ line = File.readlines(source, chomp: true).find do |entry|
151
+ entry == GITIGNORE_ACE_LOCAL_ENTRY
152
+ end
153
+ return unless line
154
+
155
+ if @dry_run
156
+ puts " Would append: #{line} -> #{target}"
157
+ return
158
+ end
159
+
160
+ File.open(target, "a") do |file|
161
+ file.write("\n") unless existing_content.end_with?("\n") || existing_content.empty?
162
+ file.puts line
163
+ end
164
+
165
+ @copied_files << target
166
+ puts " Appended: #{line} -> #{target}" if @verbose
167
+ end
168
+
169
+ def gitignore_entry_present?(content, entry)
170
+ content.each_line.any? do |line|
171
+ normalized = line.strip
172
+ next false if normalized.empty? || normalized.start_with?("#")
173
+
174
+ normalized == entry
175
+ end
176
+ end
177
+
178
+ def project_root
179
+ @project_root ||= Ace::Support::Config.find_project_root(start_path: Dir.pwd) || Dir.pwd
180
+ end
181
+
101
182
  def print_summary
102
183
  return if @dry_run
103
184
 
@@ -3,7 +3,7 @@
3
3
  module Ace
4
4
  module Support
5
5
  module Config
6
- VERSION = '0.10.2'
6
+ VERSION = '0.11.2'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ace-support-config
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ version: 0.11.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michal Czyz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-04-01 00:00:00.000000000 Z
10
+ date: 2026-04-20 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ace-support-fs
@@ -66,6 +66,7 @@ files:
66
66
  - LICENSE
67
67
  - README.md
68
68
  - Rakefile
69
+ - docs/demo/ace-config-bootstrap-root-files.tape.yml
69
70
  - docs/demo/ace-config-getting-started.tape.yml
70
71
  - docs/usage.md
71
72
  - exe/ace-config