carson 2.13.3 → 2.14.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 +4 -4
- data/RELEASE.md +13 -0
- data/VERSION +1 -1
- data/lib/carson/config.rb +4 -2
- data/lib/carson/runtime/local.rb +36 -10
- data/templates/.github/carson.md +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3ffc3d262a100056bf88d5d6ecd8f08b1698eab461451510f36e3213f1843f9
|
|
4
|
+
data.tar.gz: 4afaf01a5a27919d8e14de1d1685ae8c1af58e9aee93cfdc2ce8a01fe8acf4a8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 204a4d7f91d94d687b2bc083fee2a988663670195f6835f8717d13607668295f6ce4e2e6bd278599e700208da60fbcdda8809fba298206ea5fc5909accc61dda
|
|
7
|
+
data.tar.gz: '09cfed5c094db7d7b24b4eb17673bcb226efa21b3615145eac4c6acc396b3ea1b95efcd4e92e6c017274474c5ebe8cd0c9e851af57389e96ea734bd8e72a5db0'
|
data/RELEASE.md
CHANGED
|
@@ -5,6 +5,19 @@ Release-note scope rule:
|
|
|
5
5
|
- `RELEASE.md` records only version deltas, breaking changes, and migration actions.
|
|
6
6
|
- Operational usage guides live in `MANUAL.md` and `API.md`.
|
|
7
7
|
|
|
8
|
+
## 2.14.0 — Superseded File Cleanup on Template Apply
|
|
9
|
+
|
|
10
|
+
### What changed
|
|
11
|
+
|
|
12
|
+
- `carson template apply` now automatically removes files that Carson previously managed but has since renamed or replaced. Running `carson template apply` in a governed repo after upgrading to 2.14.0 will delete `.github/carson-instructions.md` without any manual intervention.
|
|
13
|
+
- `carson template check` reports superseded files present in the repo as stale, listed with a `— superseded` annotation. Exit code `2` (BLOCK) if any stale files are detected.
|
|
14
|
+
- `offboard` also removes superseded files as part of full Carson cleanup.
|
|
15
|
+
- `carson.md` updated to reflect the new `template apply` behaviour.
|
|
16
|
+
|
|
17
|
+
### No migration required
|
|
18
|
+
|
|
19
|
+
No manual steps needed. Run `carson template apply` — Carson handles the rest.
|
|
20
|
+
|
|
8
21
|
## 2.13.3 — Rename carson-instructions.md to carson.md
|
|
9
22
|
|
|
10
23
|
### What changed
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.14.0
|
data/lib/carson/config.rb
CHANGED
|
@@ -8,7 +8,7 @@ module Carson
|
|
|
8
8
|
class Config
|
|
9
9
|
attr_accessor :git_remote
|
|
10
10
|
attr_reader :main_branch, :protected_branches, :hooks_base_path, :required_hooks,
|
|
11
|
-
:path_groups, :template_managed_files,
|
|
11
|
+
:path_groups, :template_managed_files, :template_superseded_files,
|
|
12
12
|
:lint_policy_source,
|
|
13
13
|
:review_wait_seconds, :review_poll_seconds, :review_max_polls, :review_sweep_window_days,
|
|
14
14
|
:review_sweep_states, :review_disposition_prefix, :review_risk_keywords,
|
|
@@ -48,7 +48,8 @@ module Carson
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"template" => {
|
|
51
|
-
"managed_files" => [ ".github/carson.md", ".github/copilot-instructions.md", ".github/CLAUDE.md", ".github/AGENTS.md", ".github/pull_request_template.md", ".github/workflows/carson-lint.yml" ]
|
|
51
|
+
"managed_files" => [ ".github/carson.md", ".github/copilot-instructions.md", ".github/CLAUDE.md", ".github/AGENTS.md", ".github/pull_request_template.md", ".github/workflows/carson-lint.yml" ],
|
|
52
|
+
"superseded_files" => [ ".github/carson-instructions.md" ]
|
|
52
53
|
},
|
|
53
54
|
"lint" => {
|
|
54
55
|
"policy_source" => "wanghailei/lint.git"
|
|
@@ -216,6 +217,7 @@ module Carson
|
|
|
216
217
|
@path_groups = fetch_hash( hash: fetch_hash( hash: data, key: "scope" ), key: "path_groups" ).transform_values { |value| normalize_patterns( value: value ) }
|
|
217
218
|
|
|
218
219
|
@template_managed_files = fetch_string_array( hash: fetch_hash( hash: data, key: "template" ), key: "managed_files" )
|
|
220
|
+
@template_superseded_files = fetch_optional_string_array( hash: fetch_hash( hash: data, key: "template" ), key: "superseded_files" )
|
|
219
221
|
lint_hash = fetch_hash( hash: data, key: "lint" )
|
|
220
222
|
@lint_policy_source = lint_hash.fetch( "policy_source", "" ).to_s.strip
|
|
221
223
|
|
data/lib/carson/runtime/local.rb
CHANGED
|
@@ -339,27 +339,34 @@ module Carson
|
|
|
339
339
|
puts_verbose ""
|
|
340
340
|
puts_verbose "[Template Sync Check]"
|
|
341
341
|
results = template_results
|
|
342
|
+
stale = template_superseded_present
|
|
342
343
|
drift_count = results.count { |entry| entry.fetch( :status ) == "drift" }
|
|
343
344
|
error_count = results.count { |entry| entry.fetch( :status ) == "error" }
|
|
345
|
+
stale_count = stale.count
|
|
344
346
|
results.each do |entry|
|
|
345
347
|
puts_verbose "template_file: #{entry.fetch( :file )} status=#{entry.fetch( :status )} reason=#{entry.fetch( :reason )}"
|
|
346
348
|
end
|
|
347
|
-
puts_verbose "
|
|
349
|
+
stale.each { |file| puts_verbose "template_file: #{file} status=stale reason=superseded" }
|
|
350
|
+
puts_verbose "template_summary: total=#{results.count} drift=#{drift_count} stale=#{stale_count} error=#{error_count}"
|
|
348
351
|
unless verbose?
|
|
349
|
-
if drift_count.positive?
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
352
|
+
if ( drift_count + stale_count ).positive?
|
|
353
|
+
summary_parts = []
|
|
354
|
+
summary_parts << "#{drift_count} of #{results.count} drifted" if drift_count.positive?
|
|
355
|
+
summary_parts << "#{stale_count} stale" if stale_count.positive?
|
|
356
|
+
puts_line "Templates: #{summary_parts.join( ", " )}"
|
|
357
|
+
results.select { |entry| entry.fetch( :status ) == "drift" }.each { |entry| puts_line " #{entry.fetch( :file )}" }
|
|
358
|
+
stale.each { |file| puts_line " #{file} — superseded" }
|
|
353
359
|
else
|
|
354
360
|
puts_line "Templates: #{results.count} files in sync"
|
|
355
361
|
end
|
|
356
362
|
end
|
|
357
363
|
return EXIT_ERROR if error_count.positive?
|
|
358
364
|
|
|
359
|
-
drift_count.positive? ? EXIT_BLOCK : EXIT_OK
|
|
365
|
+
( drift_count + stale_count ).positive? ? EXIT_BLOCK : EXIT_OK
|
|
360
366
|
end
|
|
361
367
|
|
|
362
368
|
# Applies managed template files as full-file writes from Carson sources.
|
|
369
|
+
# Also removes superseded files that are no longer part of the managed set.
|
|
363
370
|
def template_apply!
|
|
364
371
|
fingerprint_status = block_if_outsider_fingerprints!
|
|
365
372
|
return fingerprint_status unless fingerprint_status.nil?
|
|
@@ -367,6 +374,7 @@ module Carson
|
|
|
367
374
|
puts_verbose ""
|
|
368
375
|
puts_verbose "[Template Sync Apply]"
|
|
369
376
|
results = template_results
|
|
377
|
+
stale = template_superseded_present
|
|
370
378
|
applied = 0
|
|
371
379
|
results.each do |entry|
|
|
372
380
|
if entry.fetch( :status ) == "error"
|
|
@@ -386,11 +394,22 @@ module Carson
|
|
|
386
394
|
applied += 1
|
|
387
395
|
end
|
|
388
396
|
|
|
397
|
+
removed = 0
|
|
398
|
+
stale.each do |file|
|
|
399
|
+
file_path = resolve_repo_path!( relative_path: file, label: "template.superseded_files entry #{file}" )
|
|
400
|
+
File.delete( file_path )
|
|
401
|
+
puts_verbose "template_file: #{file} status=removed reason=superseded"
|
|
402
|
+
removed += 1
|
|
403
|
+
end
|
|
404
|
+
|
|
389
405
|
error_count = results.count { |entry| entry.fetch( :status ) == "error" }
|
|
390
|
-
puts_verbose "template_apply_summary: updated=#{applied} error=#{error_count}"
|
|
406
|
+
puts_verbose "template_apply_summary: updated=#{applied} removed=#{removed} error=#{error_count}"
|
|
391
407
|
unless verbose?
|
|
392
|
-
if applied.positive?
|
|
393
|
-
|
|
408
|
+
if applied.positive? || removed.positive?
|
|
409
|
+
summary_parts = []
|
|
410
|
+
summary_parts << "#{applied} updated" if applied.positive?
|
|
411
|
+
summary_parts << "#{removed} removed" if removed.positive?
|
|
412
|
+
puts_line "Templates applied (#{summary_parts.join( ", " )})."
|
|
394
413
|
else
|
|
395
414
|
puts_line "Templates in sync."
|
|
396
415
|
end
|
|
@@ -428,6 +447,13 @@ module Carson
|
|
|
428
447
|
config.template_managed_files.map { |managed_file| template_result_for_file( managed_file: managed_file ) }
|
|
429
448
|
end
|
|
430
449
|
|
|
450
|
+
def template_superseded_present
|
|
451
|
+
config.template_superseded_files.select do |file|
|
|
452
|
+
file_path = resolve_repo_path!( relative_path: file, label: "template.superseded_files entry #{file}" )
|
|
453
|
+
File.file?( file_path )
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
431
457
|
# Calculates whole-file expected content and returns sync status plus apply payload.
|
|
432
458
|
def template_result_for_file( managed_file: )
|
|
433
459
|
# Try subdirectory-aware path first (e.g. .github/workflows/carson-lint.yml),
|
|
@@ -764,7 +790,7 @@ module Carson
|
|
|
764
790
|
end
|
|
765
791
|
|
|
766
792
|
def offboard_cleanup_targets
|
|
767
|
-
( config.template_managed_files + [
|
|
793
|
+
( config.template_managed_files + config.template_superseded_files + [
|
|
768
794
|
".github/workflows/carson-governance.yml",
|
|
769
795
|
".github/workflows/carson_policy.yml",
|
|
770
796
|
".carson.yml",
|
data/templates/.github/carson.md
CHANGED
|
@@ -11,8 +11,8 @@ Carson has no `commit`, `push`, or `pr` commands. Use `git` and `gh` for those.
|
|
|
11
11
|
**Before committing:**
|
|
12
12
|
```bash
|
|
13
13
|
carson audit # full governance check — run before every commit
|
|
14
|
-
carson template check # detect drift in .github/* managed files
|
|
15
|
-
carson template apply # fix drift
|
|
14
|
+
carson template check # detect drift in .github/* managed files, including stale superseded files
|
|
15
|
+
carson template apply # fix drift and remove superseded files
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
**Before recommending merge:**
|