git 5.0.0.beta.1 → 5.0.0.beta.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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/copilot-instructions.md +6 -0
  3. data/.github/prompts/iteratively-address-copilot-reviews.prompt.md +188 -0
  4. data/.github/skills/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +22 -0
  5. data/.github/skills/extract-facade-from-base-lib/SKILL.md +28 -14
  6. data/.github/skills/facade-implementation/SKILL.md +14 -0
  7. data/.github/skills/facade-test-conventions/SKILL.md +14 -0
  8. data/.rubocop.yml +5 -0
  9. data/README.md +51 -11
  10. data/UPGRADING.md +141 -0
  11. data/git.gemspec +5 -0
  12. data/lib/git/branch.rb +7 -18
  13. data/lib/git/branches.rb +2 -10
  14. data/lib/git/command_line/base.rb +10 -0
  15. data/lib/git/command_line/capturing.rb +5 -3
  16. data/lib/git/command_line/streaming.rb +5 -3
  17. data/lib/git/command_line.rb +3 -3
  18. data/lib/git/commands/base.rb +7 -6
  19. data/lib/git/commands/cat_file/batch.rb +6 -1
  20. data/lib/git/commands/cat_file/raw.rb +7 -1
  21. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +5 -0
  22. data/lib/git/commands/show_ref/exclude_existing.rb +1 -1
  23. data/lib/git/commands/update_ref/batch.rb +1 -1
  24. data/lib/git/commands/version.rb +5 -0
  25. data/lib/git/commands.rb +5 -7
  26. data/lib/git/config.rb +17 -0
  27. data/lib/git/config_entry_info.rb +106 -0
  28. data/lib/git/configuring.rb +665 -0
  29. data/lib/git/deprecation.rb +9 -0
  30. data/lib/git/diff.rb +4 -8
  31. data/lib/git/diff_path_status.rb +2 -13
  32. data/lib/git/diff_stats.rb +1 -9
  33. data/lib/git/execution_context/global.rb +3 -28
  34. data/lib/git/execution_context/repository.rb +30 -41
  35. data/lib/git/execution_context.rb +43 -24
  36. data/lib/git/log.rb +3 -9
  37. data/lib/git/object.rb +14 -21
  38. data/lib/git/parsers/config_entry.rb +110 -0
  39. data/lib/git/parsers/ls_remote.rb +79 -0
  40. data/lib/git/remote.rb +7 -20
  41. data/lib/git/repository/branching.rb +183 -12
  42. data/lib/git/repository/committing.rb +64 -68
  43. data/lib/git/repository/configuring.rb +208 -13
  44. data/lib/git/repository/context_helpers.rb +264 -0
  45. data/lib/git/repository/factories.rb +682 -0
  46. data/lib/git/repository/inspecting.rb +99 -0
  47. data/lib/git/repository/maintenance.rb +65 -0
  48. data/lib/git/repository/merging.rb +63 -1
  49. data/lib/git/repository/object_operations.rb +133 -35
  50. data/lib/git/repository/path_resolver.rb +1 -1
  51. data/lib/git/repository/remote_operations.rb +166 -21
  52. data/lib/git/repository/staging.rb +187 -23
  53. data/lib/git/repository/stashing.rb +39 -3
  54. data/lib/git/repository/status_operations.rb +21 -0
  55. data/lib/git/repository.rb +68 -129
  56. data/lib/git/stash.rb +2 -9
  57. data/lib/git/stashes.rb +2 -7
  58. data/lib/git/status.rb +8 -17
  59. data/lib/git/version.rb +2 -2
  60. data/lib/git/worktree.rb +2 -15
  61. data/lib/git/worktrees.rb +2 -15
  62. data/lib/git.rb +180 -77
  63. data/redesign/3_architecture_implementation.md +148 -111
  64. data/redesign/Phase 4 - Step A.md +360 -0
  65. data/redesign/beta_release.md +107 -0
  66. data/redesign/c1c2_audit.md +566 -0
  67. data/redesign/c1c2_bucket6_lib_orphans.md +626 -0
  68. data/redesign/config_design.rb +501 -0
  69. metadata +19 -5
  70. data/lib/git/base.rb +0 -1204
  71. data/lib/git/lib.rb +0 -2855
@@ -0,0 +1,566 @@
1
+ # C1c-2 Audit: `Git::Base` → `Git::Repository` Inventory
2
+
3
+ **Date:** 2026-06-06
4
+
5
+ **Branch:** `agents/c1c2-audit-inventory-documentation`
6
+
7
+ **Produced by:** Step C1c-2 (research-and-documentation only; no production code changed)
8
+
9
+ This document is the exhaustive public-method inventory required before any
10
+ remediation work (PR 2–4) begins. Every public instance method on `Git::Base`
11
+ is compared against `Git::Repository`, and every orphaned public method on
12
+ `Git::Lib` that would silently break when `Git::Lib` is removed in Phase 4 is
13
+ surfaced.
14
+
15
+ ## Status Legend
16
+
17
+ | Status | Meaning |
18
+ |--------|---------|
19
+ | ✅ | **Already covered** — method exists on `Git::Repository` (or a module it includes) with equivalent behavior |
20
+ | ⬜ | **Needs migration** — method is absent from `Git::Repository`; should be migrated |
21
+ | ❌ | **Intentional removal** — method should not survive in v5; must be deprecated with upgrade notes before C1d |
22
+ | ⚠️ | **Signature gap** — method exists on `Git::Repository` but its parameter signature is inconsistent with the C1c-1 policy (legacy-contract vs 5.x-native) |
23
+ | 🔍 | **Needs human decision** — unclear classification; surfaced for the human reviewer |
24
+
25
+ ---
26
+
27
+ ## 1. Summary Counts
28
+
29
+ | Bucket | ✅ | ⬜ | ❌ | ⚠️ | 🔍 | Total |
30
+ |--------|----|----|----|----|-----|-------|
31
+ | 1 — Path/accessors | 4 | 0 | 0 | 0 | 0 | 4 |
32
+ | 2 — Compatibility aliases & wrappers | 8 | 0 | 0 | 0 | 0 | 8 |
33
+ | 3 — Low-level public methods | 7 | 0 | 0 | 0 | 0 | 7 |
34
+ | 4 — Factory & domain-object returns | 12 | 0 | 0 | 0 | 0 | 12 |
35
+ | 5 — Keyword-arg signature review | 9 | 0 | 0 | 0 | 0 | 9 |
36
+ | 6 — `Git::Lib` orphaned public methods | — | — | — | — | — | **✅ see §7** |
37
+ | **Grand total (Buckets 1–5)** | **40** | **0** | **0** | **0** | **0** | **40** |
38
+
39
+ > ✅ **All Bucket 6 orphans resolved** — see §7 for the full breakdown.
40
+ > All 36 promotable methods have been promoted (or kept as deprecated wrappers),
41
+ > and all 12 internal plumbing methods have been annotated `@api private`.
42
+
43
+ ---
44
+
45
+ ## 2. Full Inventory Table
46
+
47
+ Sorted by bucket, then alphabetically within bucket.
48
+
49
+ | Method | Bucket | Status | Destination / Notes |
50
+ |--------|--------|--------|---------------------|
51
+ | `dir` | 1 | ✅ | `Git::Repository#dir` (repository.rb:89) |
52
+ | `index` | 1 | ✅ | `Git::Repository#index` (repository.rb:113) |
53
+ | `repo` | 1 | ✅ | `Git::Repository#repo` (repository.rb:101) |
54
+ | `repo_size` | 1 | ✅ | `Git::Repository#repo_size` (repository.rb:131) |
55
+ | `checkout` | 2 | ✅ | Fixed in PR 4 — `checkout(branch = nil, opts = {})` with `is_a?(Hash)` guard handles all 4.x calling conventions safely in Ruby 3 (see §5) |
56
+ | `diff_name_status` | 2 | ✅ | `alias diff_name_status diff_path_status` already present in `Git::Repository::Diffing` (diffing.rb:382) |
57
+ | `is_branch?` | 2 | ✅ | Deprecated stub added to `Git::Repository::Branching` delegating to `branch?` |
58
+ | `is_local_branch?` | 2 | ✅ | Deprecated stub added to `Git::Repository::Branching` delegating to `local_branch?` |
59
+ | `is_remote_branch?` | 2 | ✅ | Deprecated stub added to `Git::Repository::Branching` delegating to `remote_branch?` |
60
+ | `remove` | 2 | ✅ | `alias remove rm` added to `Git::Repository::Staging` |
61
+ | `reset_hard` | 2 | ✅ | `Git::Repository::Staging#reset_hard` — deprecated wrapper delegating to `reset(commitish, hard: true)` |
62
+ | `revparse` | 2 | ✅ | `alias revparse rev_parse` added to `Git::Repository::ObjectOperations` |
63
+ | `apply` | 3 | ✅ | `Git::Repository::Staging#apply(file)` added — PR 3; `File.exist?` guard and `chdir:` execution option preserved |
64
+ | `apply_mail` | 3 | ✅ | `Git::Repository::Staging#apply_mail(file)` added — PR 3; `File.exist?` guard preserved |
65
+ | `describe` | 3 | ✅ | `Git::Repository::Inspecting#describe(committish = nil, opts = {})` added — PR 3; `exact-match` → `exact_match` key translation preserved |
66
+ | `gc` | 3 | ✅ | `Git::Repository::Maintenance#gc` added (new `Git::Repository::Maintenance` module created) — PR 3 |
67
+ | `read_tree` | 3 | ✅ | `Git::Repository::Staging#read_tree(treeish, opts = {})` added — PR 3 |
68
+ | `repack` | 3 | ✅ | `Git::Repository::Maintenance#repack` added (new `Maintenance` module) — PR 3 |
69
+ | `cat_file` | 3 | ✅ | `alias cat_file cat_file_contents` added to `Git::Repository::ObjectOperations`; `alias cat_file cat_file_contents` added to `Git::Base` — per §6 decision; `cat_file_contents` remains the 5.x-native name |
70
+ | `add_tag` | 4 | ✅ | `Git::Repository::ObjectOperations#add_tag` |
71
+ | `branch` | 4 | ✅ | `Git::Repository::Branching#branch` |
72
+ | `branches` | 4 | ✅ | `Git::Repository::Branching#branches` |
73
+ | `delete_tag` | 4 | ✅ | `Git::Repository::ObjectOperations#delete_tag` |
74
+ | `gblob` | 4 | ✅ | `Git::Repository::ObjectOperations#gblob` |
75
+ | `gcommit` | 4 | ✅ | `Git::Repository::ObjectOperations#gcommit` |
76
+ | `gtree` | 4 | ✅ | `Git::Repository::ObjectOperations#gtree` |
77
+ | `object` | 4 | ✅ | `Git::Repository::ObjectOperations#object` |
78
+ | `remote` | 4 | ✅ | `Git::Repository::RemoteOperations#remote` |
79
+ | `remotes` | 4 | ✅ | `Git::Repository::RemoteOperations#remotes` |
80
+ | `tag` | 4 | ✅ | `Git::Repository::ObjectOperations#tag` — returns `Git::Object::Tag` ✅ |
81
+ | `tags` | 4 | ✅ | `Git::Repository::ObjectOperations#tags` — returns `Array<Git::Object::Tag>` ✅ |
82
+ | `add` | 5 | ✅ | `Git::Base#add(paths = '.', **)` already uses `**`; `Staging#add(paths = '.', **)` matches — no legacy-contract violation |
83
+ | `checkout_file` | 5 | ✅ | Branching#checkout_file: `(version, file)` — matches `Git::Base` signature ✅ |
84
+ | `commit` | 5 | ✅ | Fixed in PR 4 — `commit(message, opts = {})` per 4.x contract; `message` is now required |
85
+ | `commit_all` | 5 | ✅ | Fixed in PR 4 — `commit_all(message, opts = {})` per 4.x contract |
86
+ | `commit_tree` | 5 | ✅ | Fixed in PR 4 — `commit_tree(tree = nil, opts = {})` per 4.x contract |
87
+ | `fsck` | 5 | ✅ | Resolved — classified as `legacy-contract`; anonymous `**` in `fsck(*objects, **)` is functionally equivalent to `(*objects, **opts)` for all callers; no signature change required |
88
+ | `reset` | 5 | ✅ | Fixed in PR 4 — `reset(commitish = nil, opts = {})` per 4.x contract |
89
+ | `revert` | 5 | ✅ | Merging#revert: `(commitish = nil, opts = {})` — matches `Git::Base` signature ✅ |
90
+ | `write_and_commit_tree` | 5 | ✅ | Fixed in PR 4 — `write_and_commit_tree(opts = {})` per 4.x contract |
91
+
92
+ ---
93
+
94
+ ## 3. ⬜ Migration Candidates
95
+
96
+ ### Bucket 2
97
+
98
+ #### `remove`
99
+
100
+ > ✅ **Completed** — `alias remove rm` added to `Git::Repository::Staging` (PR 2).
101
+
102
+ **Current implementation:** `Git::Base` line 420 — `alias remove rm`.
103
+ **Proposed destination:** `Git::Repository::Staging` — add `alias remove rm` after the `rm` method.
104
+ **Classification:** `legacy-contract` — 4.x public API alias.
105
+ **Effort:** trivial (one-line alias).
106
+
107
+ #### `revparse`
108
+
109
+ > ✅ **Completed** — `alias revparse rev_parse` added to `Git::Repository::ObjectOperations` (PR 2).
110
+
111
+ **Current implementation:** `Git::Base` line 879 — `alias revparse rev_parse`.
112
+ **Proposed destination:** `Git::Repository::ObjectOperations` — add `alias revparse rev_parse`.
113
+ **Classification:** `legacy-contract` — widely used 4.x shorthand.
114
+ **Effort:** trivial (one-line alias).
115
+
116
+ #### `is_branch?`
117
+
118
+ > ✅ **Completed** — deprecated stub `is_branch?(branch)` added to `Git::Repository::Branching`, emitting `Git::Deprecation.warn` and delegating to `branch?` (PR 2).
119
+
120
+ **Current implementation:** `Git::Base#is_branch?(branch)` (base.rb:325–331) — already carries `Git::Deprecation.warn` in 4.x and v5. `Git::Repository::Branching#branch?` is the replacement.
121
+ **Proposed destination:** `Git::Repository::Branching` — add deprecated stub `is_branch?(branch)` that emits `Git::Deprecation.warn` and delegates to `branch?`.
122
+ **Classification:** `legacy-contract` — must be present on `Git::Repository` so callers receive the deprecation warning rather than `NoMethodError`.
123
+ **Effort:** trivial (one-method deprecated stub; `@deprecated` YARD tag added).
124
+
125
+ #### `is_local_branch?`
126
+
127
+ > ✅ **Completed** — deprecated stub `is_local_branch?(branch)` added to `Git::Repository::Branching`, emitting `Git::Deprecation.warn` and delegating to `local_branch?` (PR 2).
128
+
129
+ **Current implementation:** `Git::Base#is_local_branch?(branch)` (base.rb:299–305) — already carries `Git::Deprecation.warn` in 4.x and v5. `Git::Repository::Branching#local_branch?` is the replacement.
130
+ **Proposed destination:** `Git::Repository::Branching` — add deprecated stub `is_local_branch?(branch)` that emits `Git::Deprecation.warn` and delegates to `local_branch?`.
131
+ **Classification:** `legacy-contract` — same rationale as `is_branch?`.
132
+ **Effort:** trivial (one-method deprecated stub; `@deprecated` YARD tag added).
133
+
134
+ #### `is_remote_branch?`
135
+
136
+ > ✅ **Completed** — deprecated stub `is_remote_branch?(branch)` added to `Git::Repository::Branching`, emitting `Git::Deprecation.warn` and delegating to `remote_branch?` (PR 2).
137
+
138
+ **Current implementation:** `Git::Base#is_remote_branch?(branch)` (base.rb:312–318) — already carries `Git::Deprecation.warn` in 4.x and v5. `Git::Repository::Branching#remote_branch?` is the replacement.
139
+ **Proposed destination:** `Git::Repository::Branching` — add deprecated stub `is_remote_branch?(branch)` that emits `Git::Deprecation.warn` and delegates to `remote_branch?`.
140
+ **Classification:** `legacy-contract` — same rationale as `is_branch?`.
141
+ **Effort:** trivial (one-method deprecated stub; `@deprecated` YARD tag added).
142
+
143
+ #### `reset_hard`
144
+
145
+ > ✅ **Completed** — deprecated wrapper `reset_hard(commitish = nil, opts = {})` added to `Git::Repository::Staging`, emitting `Git::Deprecation.warn` and delegating to `reset(commitish, hard: true)` (PR 2).
146
+
147
+ **Current implementation:** `Git::Base#reset_hard(commitish = nil, opts = {})` (base.rb:431) — already carries a `Git::Deprecation.warn` and a YARD `@deprecated` tag in v5. In 4.x it was a non-deprecated public method.
148
+ **Proposed destination:** `Git::Repository::Staging` — add a deprecated wrapper method `reset_hard(commitish = nil, opts = {})` that emits `Git::Deprecation.warn` and delegates to `reset(commitish, **opts.merge(hard: true))`.
149
+ **Classification:** `legacy-contract` — must be present on `Git::Repository` so that callers receive the deprecation warning rather than a `NoMethodError` when `Git.open` switches to return `Git::Repository`.
150
+ **Effort:** trivial (one-method deprecated wrapper; `@deprecated` tag already written in `Git::Base`).
151
+
152
+ ### Bucket 3
153
+
154
+ #### `describe`
155
+
156
+ > ✅ **Completed** — `Git::Repository::Inspecting#describe(committish = nil, opts = {})` added; `exact-match` → `exact_match` key translation preserved; `Git::Base` delegator wired (PR 3).
157
+
158
+ **Current implementation:** `Git::Base#describe(committish = nil, opts = {})` (base.rb:466) → `lib.describe(committish, opts)`. `Git::Lib#describe` (lib.rb:223) → `Git::Commands::Describe.new(self).call(...)`. `Git::Commands::Describe` ✅ exists.
159
+ **Proposed destination:** `Git::Repository::Inspecting` — already houses `show` and `fsck`; `describe` is a read-only inspection operation.
160
+ **Classification:** `legacy-contract` — preserve `(committish = nil, opts = {})` exactly.
161
+ **Effort:** moderate — needs option allowlist cross-referenced against 4.x `*_OPTION_MAP`; the `exact-match` → `exact_match` key translation currently in `Git::Lib#describe` must be preserved in the facade.
162
+
163
+ #### `gc`
164
+
165
+ > ✅ **Completed** — `Git::Repository::Maintenance#gc` added in new `Git::Repository::Maintenance` topic module; `Git::Base` delegator wired (PR 3).
166
+
167
+ **Current implementation:** `Git::Base#gc` (base.rb:699) → `lib.gc`. `Git::Lib#gc` (lib.rb:1778) → `Git::Commands::Gc.new(self).call(prune: true, aggressive: true, auto: true)`. `Git::Commands::Gc` ✅ exists.
168
+ **Proposed destination:** New `Git::Repository::Maintenance` topic module (pair with `repack`). Alternatively `Git::Repository::Inspecting` if a new module is not justified.
169
+ **Classification:** `legacy-contract` — preserve `()` (no arguments).
170
+ **Effort:** trivial — zero-arity facade; fixed options forwarded to command class.
171
+
172
+ #### `repack`
173
+
174
+ > ✅ **Completed** — `Git::Repository::Maintenance#repack` added in `Git::Repository::Maintenance` topic module; `Git::Base` delegator wired (PR 3).
175
+
176
+ **Current implementation:** `Git::Base#repack` (base.rb:695) → `lib.repack`. `Git::Lib#repack` (lib.rb:1774) → `Git::Commands::Repack.new(self).call(a: true, d: true)`. `Git::Commands::Repack` ✅ exists.
177
+ **Proposed destination:** New `Git::Repository::Maintenance` topic module (pair with `gc`).
178
+ **Classification:** `legacy-contract` — preserve `()` (no arguments).
179
+ **Effort:** trivial — zero-arity facade; fixed options forwarded to command class.
180
+
181
+ #### `apply`
182
+
183
+ > ✅ **Completed** — `Git::Repository::Staging#apply(file)` added; `File.exist?` guard and `chdir:` execution option preserved; `Git::Base` delegator wired (PR 3).
184
+
185
+ **Current implementation:** `Git::Base#apply(file)` (base.rb:754) — applies patch only when `File.exist?(file)`; delegates to `lib.apply(file)`. `Git::Lib#apply` (lib.rb:1248) → `Git::Commands::Apply.new(self).call(...)`. `Git::Commands::Apply` ✅ exists.
186
+ **Proposed destination:** `Git::Repository::Staging` — already owns low-level index operations; `apply` is a patch-application operation closely related to staging.
187
+ **Classification:** `legacy-contract` — preserve `(file)` signature and the `File.exist?` guard in `Git::Base`.
188
+ **Effort:** moderate — must preserve the `File.exist?` guard and the `chdir: @git_work_dir` execution option. Tests must cover both the case where the file exists (patch applied) and where it does not (no-op).
189
+
190
+ #### `apply_mail`
191
+
192
+ > ✅ **Completed** — `Git::Repository::Staging#apply_mail(file)` added alongside `apply`; `File.exist?` guard preserved; `Git::Base` delegator wired (PR 3).
193
+
194
+ **Current implementation:** `Git::Base#apply_mail(file)` (base.rb:760) — applies `git am` only when `File.exist?(file)`; delegates to `lib.apply_mail(file)`. `Git::Lib#apply_mail` (lib.rb:1252) → `Git::Commands::Am::Apply.new(self).call(...)`. `Git::Commands::Am` ✅ exists.
195
+ **Proposed destination:** `Git::Repository::Staging` — alongside `apply`.
196
+ **Classification:** `legacy-contract` — preserve `(file)` signature and the `File.exist?` guard.
197
+ **Effort:** moderate — same concerns as `apply`. Tests must cover both the case where the file exists (patch applied) and where it does not (no-op).
198
+
199
+ #### `read_tree`
200
+
201
+ > ✅ **Completed** — `Git::Repository::Staging#read_tree(treeish, opts = {})` added; `Git::Base` delegator wired (PR 3).
202
+
203
+ **Current implementation:** `Git::Base#read_tree(treeish, opts = {})` (base.rb:813) → `lib.read_tree(treeish, opts)`. `Git::Lib#read_tree` (lib.rb:1798) → `Git::Commands::ReadTree.new(self).call(...)`. `Git::Commands::ReadTree` ✅ exists.
204
+ **Proposed destination:** `Git::Repository::Staging` — already owns `checkout_index`, `write_tree`, etc.
205
+ **Classification:** `legacy-contract` — preserve `(treeish, opts = {})`.
206
+ **Effort:** trivial — thin orchestration; the option allowlist (`:prefix`) is already defined in `Git::Lib::READ_TREE_ALLOWED_OPTS`.
207
+
208
+ ---
209
+
210
+ ## 4. ❌ Intentional Removals
211
+
212
+ > There are no intentional removals in Buckets 1–5. All deprecated methods
213
+ > from 4.x must be present on `Git::Repository` as deprecated stubs so callers
214
+ > receive a `Git::Deprecation.warn` rather than a `NoMethodError` when
215
+ > `Git.open` switches to return `Git::Repository`.
216
+
217
+ ---
218
+
219
+ ## 5. ⚠️ Signature Gaps
220
+
221
+ Six gaps are `legacy-contract` violations. Five are cases where the facade
222
+ method uses `**opts` or anonymous `**` keyword-splat where the 4.x predecessor
223
+ used a positional `opts = {}` hash — in Ruby 3, passing a bare `Hash` variable
224
+ as the last positional argument to a `**`-accepting method raises `ArgumentError`.
225
+ One (`checkout`) uses explicit named parameters where 4.x used an all-splat form.
226
+
227
+ **Note on `add`:** `Git::Base#add(paths = '.', **)` already uses `**` (see
228
+ base.rb:198), so `Git::Repository::Staging#add(paths = '.', **)` is consistent
229
+ with the existing `Git::Base` signature and is **not** a legacy-contract
230
+ violation. `add` does not appear in the fixes below.
231
+
232
+ ### `Git::Repository::Branching#checkout`
233
+
234
+ > ✅ **Completed — Fixed in PR 4.** Signature changed to `checkout(branch = nil, opts = {})` with an `is_a?(Hash)` guard at the top of the method body that handles the case where `branch` is passed as a positional hash. This form handles all three 4.x calling conventions safely in Ruby 3: positional-hash callers, keyword callers, and mixed. The internal validation and option-translation logic (`assert_valid_opts!`, `translate_checkout_opts`) were preserved unchanged.
235
+
236
+ **Pre-fix signature:** `checkout(branch = nil, options = {})` (branching.rb:116)
237
+ **Corrected signature:** `checkout(branch = nil, opts = {})` with `is_a?(Hash)` guard (legacy-contract)
238
+ **C1c-1 rule violated:** Rule 1 — `Git::Base#checkout` in 4.x used `(*, **)`. The explicit `(branch = nil, options = {})` in the facade does not accept keyword arguments; callers passing keyword-style options (e.g. `checkout('main', force: true)`) will receive `ArgumentError` in Ruby 3 because there is no `**` acceptor in the signature.
239
+ **Applied fix:** Kept `(branch = nil, opts = {})` and added an `is_a?(Hash)` guard at the top of the method body to handle the positional-hash calling convention. The original planned approach (`*args, **kwargs` splat with manual unpacking) was not used; the guard achieves the same safety with less disruption to the implementation body.
240
+
241
+ ### `Git::Repository::Staging#reset`
242
+
243
+ > ✅ **Completed — Fixed in PR 4.** Signature changed from `reset(commitish = nil, **)` to `reset(commitish = nil, opts = {})`.
244
+
245
+ **Pre-fix signature:** `reset(commitish = nil, **)` (staging.rb:88)
246
+ **Corrected signature:** `reset(commitish = nil, opts = {})` (legacy-contract)
247
+ **C1c-1 rule violated:** Rule 1. `Git::Base#reset` used positional `opts = {}`.
248
+ **Applied fix:** Changed `**)` to `opts = {})`.
249
+
250
+ ### `Git::Repository::Committing#commit`
251
+
252
+ > ✅ **Completed — Fixed in PR 4.** Signature changed from `commit(message = nil, **opts)` to `commit(message, opts = {})`. The default was removed from `message` (restoring the required positional per 4.x contract).
253
+
254
+ **Pre-fix signature:** `commit(message = nil, **opts)` (committing.rb:77)
255
+ **Corrected signature:** `commit(message, opts = {})` (legacy-contract)
256
+ **C1c-1 rule violated:** Rule 1. `Git::Base#commit` used `(message, opts = {})` — `message` is required. The facade also relaxed `message` to optional, which is a silent API drift.
257
+ **Applied fix:** Removed default from `message`; changed `**opts` to `opts = {}`.
258
+
259
+ ### `Git::Repository::Committing#commit_all`
260
+
261
+ > ✅ **Completed — Fixed in PR 4.** Signature changed from `commit_all(*, **)` to `commit_all(message, opts = {})`.
262
+
263
+ **Pre-fix signature:** `commit_all(*, **)` (committing.rb:110)
264
+ **Corrected signature:** `commit_all(message, opts = {})` (legacy-contract)
265
+ **C1c-1 rule violated:** Rule 1. `Git::Base#commit_all` used `(message, opts = {})`. The splatted form accepted anything and made the public contract invisible.
266
+ **Applied fix:** Restored explicit positional parameters.
267
+
268
+ ### `Git::Repository::Committing#commit_tree`
269
+
270
+ > ✅ **Completed — Fixed in PR 4.** Signature changed from `commit_tree(tree, **opts)` to `commit_tree(tree = nil, opts = {})`. Default `nil` restored to `tree` per 4.x contract.
271
+
272
+ **Pre-fix signature:** `commit_tree(tree, **opts)` (committing.rb:147)
273
+ **Corrected signature:** `commit_tree(tree = nil, opts = {})` (legacy-contract)
274
+ **C1c-1 rule violated:** Rule 1. `Git::Base#commit_tree` used `(tree = nil, opts = {})` — `tree` is optional in the legacy API.
275
+ **Applied fix:** Added default `= nil` to `tree`; changed `**opts` to `opts = {}`.
276
+
277
+ ### `Git::Repository::Committing#write_and_commit_tree`
278
+
279
+ > ✅ **Completed — Fixed in PR 4.** Signature changed from `write_and_commit_tree(**)` to `write_and_commit_tree(opts = {})`.
280
+
281
+ **Pre-fix signature:** `write_and_commit_tree(**)` (committing.rb:186)
282
+ **Corrected signature:** `write_and_commit_tree(opts = {})` (legacy-contract)
283
+ **C1c-1 rule violated:** Rule 1. `Git::Base#write_and_commit_tree` in 4.x used `(opts = {})`. The anonymous `**` splat was a legacy-contract violation.
284
+ **Applied fix:** Changed `**)` to `opts = {})` and updated the delegated call to pass `opts` as a keyword splat: `commit_tree(write_tree, **opts)`.
285
+
286
+ ---
287
+
288
+ ## 6. 🔍 Human Decisions Needed
289
+
290
+ ### `cat_file` (Bucket 3)
291
+
292
+ **Background:** `Git::Base#cat_file(objectish)` (base.rb:925) delegates to `lib.cat_file(objectish)`. However, **`Git::Lib` contains no `cat_file` method**. The method is effectively broken at runtime (calling it raises `NoMethodError`). `Git::Repository::ObjectOperations` provides `cat_file_contents(object)` which returns the raw content of a git object — the most plausible intended behavior.
293
+
294
+ **Specific question:** Should `cat_file` be:
295
+
296
+ **Option A — Alias for `cat_file_contents`:** Add `alias cat_file cat_file_contents` to `Git::Repository::ObjectOperations` and wire `Git::Base#cat_file` to delegate there. Preserves a broken API under a new implementation.
297
+
298
+ **Option B — Deprecated stub:** Add a `@deprecated` tag to `Git::Base#cat_file` directing callers to `cat_file_contents`, emit a `Git::Deprecation.warn`, and do not promote it to `Git::Repository`. The method was silently broken; promoting it may confuse callers who never successfully used it.
299
+
300
+ **Option C — Silent removal:** Remove `Git::Base#cat_file` in v5 with an upgrade note. It was broken in the current codebase and therefore has no legitimate callers.
301
+
302
+ **Recommended default if no human input:** Option B — issue a deprecation warning and point to `cat_file_contents`, which is the clear successor.
303
+
304
+ **Decision:** In 4.x, `Git::Base#cat_file` delegated to `Git::Lib#cat_file_contents`, so `cat_file` is the established public name. To preserve backward compatibility, add `alias cat_file cat_file_contents` to `Git::Repository::ObjectOperations` (keeping `cat_file_contents` as the primary 5.x-native method name), and add a `Git::Base#cat_file` delegator that forwards to the facade. Add tests for both the alias and the delegator.
305
+
306
+ > ✅ **Completed** — `alias cat_file cat_file_contents` added to `Git::Repository::ObjectOperations`; `alias cat_file cat_file_contents` added to `Git::Base` (PR 2d).
307
+
308
+ ---
309
+
310
+ ### `branch_delete` (Bucket 6 orphan — classification decision)
311
+
312
+ **Background:** `Git::Repository::Branching#branch_delete(*branches, **options)` uses keyword-arg splat. `Git::Lib#branch_delete(*branches, **options)` also uses `**options`. There is no `Git::Base#branch_delete` delegator (the method is not publicly accessible via `g.branch_delete` — it is a Bucket 6 orphan exposed only via `g.lib.branch_delete`). Because there is no 4.x `Git::Base` predecessor with a `opts = {}` signature, the `legacy-contract` rule may not apply.
313
+
314
+ **Specific question:** Should `branch_delete` be classified as:
315
+
316
+ **Option A — `5.x-native`:** The method was added to `Git::Lib` with keyword args and was never part of the public `Git::Base` surface. The `**options` signature in `Git::Repository` is therefore correct and intentional. Document as `5.x-native`.
317
+
318
+ **Option B — `legacy-contract` with signature fix:** Treat `Git::Lib#branch_delete` as the public contract source (Pattern B) and require the `Git::Repository` facade to mirror `(*branches, **options)` exactly. No change needed — the signatures already match.
319
+
320
+ **Option C — `legacy-contract` with reversion to `opts = {}`:** Revert to a positional options hash for consistency with other methods. This would break any callers already using `branch_delete` with keyword args.
321
+
322
+ **Recommended default if no human input:** Option A or B — both are acceptable since the lib.rb signature already uses keyword args. Option A is cleaner because it gives `5.x-native` status.
323
+
324
+ **Decision:** In 4.x, `Git::Lib#branch_delete(branch)` accepted a single branch with no options at all, so no 4.x caller ever passed a bare `Hash` variable as the last argument. The C1c-1 `legacy-contract` rule guards against exactly that failure mode (Ruby 3 `ArgumentError` when a bare `Hash` is passed to a `**kwargs`-accepting method); that failure mode cannot occur here. Classify as `legacy-contract` — **current signature already satisfies the contract**. The `*branches` variadic extension is a safe additive improvement; `**options` is correct because no 4.x caller passed options. No signature change required.
325
+
326
+ > ✅ **Resolved** — classified as `legacy-contract`; current `*branches, **options` signature is backward-compatible with all 4.x callers; no code change required.
327
+
328
+ ---
329
+
330
+ ### `fsck` (Bucket 5)
331
+
332
+ **Background:** `Git::Base#fsck(*objects, **opts)` (base.rb:749) and `Git::Repository::Inspecting#fsck(*objects, **)` (inspecting.rb:146) both accept keyword args. The only difference is anonymous `**` vs named `**opts`. For external callers the behavior is identical. However, the named form `**opts` is more conventional and matches the base.rb signature.
333
+
334
+ **Specific question:** Should `fsck` be:
335
+
336
+ **Option A — `legacy-contract` with minor fix:** Change `**` to `**opts` in the facade signature for clarity and consistency. Functionally equivalent; cosmetic improvement.
337
+
338
+ **Option B — `5.x-native`:** `fsck` was migrated early and the `**` anonymous form was intentional per the facade-implementation conventions. Classify as `5.x-native` and leave the signature as-is.
339
+
340
+ **Recommended default if no human input:** Option A — the named `**opts` is more readable and matches the base.rb public contract. The change is purely cosmetic.
341
+
342
+ **Decision:** In 4.x, `Git::Base#fsck` already used `*objects, **opts` (keyword args). The v5 facade `Git::Repository::Inspecting#fsck(*objects, **)` is functionally identical for all callers — the only difference is the anonymous `**` vs named `**opts`, which has no effect on the public API. Classify as `legacy-contract` (4.x signature is keyword-based). Leave the signature as-is; no change required.
343
+
344
+ > ✅ **Resolved** — classified as `legacy-contract`; no signature change made; anonymous `**` is functionally equivalent for all callers.
345
+
346
+ ---
347
+
348
+ ## 7. Bucket 6 — `Git::Lib` Orphaned Public Methods
349
+
350
+ > ✅ **All Bucket 6 orphans resolved.** Per the audit instructions a companion
351
+ > document (`redesign/c1c2_bucket6_lib_orphans.md`) was created for the
352
+ > human-decision items. All promotions and @api private annotations are complete.
353
+
354
+ The subsections below provide a high-level triage. The companion document
355
+ should contain the full per-method analysis.
356
+
357
+ ### 7.1 Scope
358
+
359
+ `Git::Lib` is declared `@api private` but `Git::Base#lib` is a public accessor,
360
+ making every public method on `Git::Lib` reachable as `g.lib.method_name`. When
361
+ `Git::Lib` is deleted in Phase 4, all such call sites silently break.
362
+
363
+ The criterion for inclusion in this bucket:
364
+ - Public instance method in `lib/git/lib.rb` (i.e., appears before `private` at line 2200)
365
+ - **No same-named delegator on `Git::Base`** (methods already covered by a
366
+ `Git::Base` wrapper appear in Buckets 1–5)
367
+
368
+ ### 7.2 Methods Already Migrated to `Git::Repository` (trivial base.rb wiring needed)
369
+
370
+ These orphans exist on `Git::Lib` and have already been migrated to a
371
+ `Git::Repository` module. The remediation is a trivial one-line delegator in
372
+ `Git::Base`. They should be batched into PR 2 or a separate lightweight PR.
373
+
374
+ | `Git::Lib` method | `Git::Repository` home | Status |
375
+ |-------------------|------------------------|--------|
376
+ | `branches_all` | `Git::Repository::Branching` | ✅ `Git::Base` delegator added (PR 2d) |
377
+ | `branch_contains(commit, branch_name = '')` | `Git::Repository::Branching` | ✅ `Git::Base` delegator added (PR 2d) |
378
+ | `branch_delete(*branches, **options)` | `Git::Repository::Branching` | ✅ `Git::Base` delegator added (PR 2d) |
379
+ | `branch_new(branch, start_point = nil, options = {})` | `Git::Repository::Branching` | ✅ `Git::Base` delegator added (PR 2d) |
380
+ | `cat_file_commit(object)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added (PR 2d) |
381
+ | `cat_file_contents(object)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added; `alias cat_file cat_file_contents` added (PR 2d) |
382
+ | `cat_file_size(object)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added (PR 2d) |
383
+ | `cat_file_tag(object)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added (PR 2d) |
384
+ | `cat_file_type(object)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added (PR 2d) |
385
+ | `config_remote(name)` | `Git::Repository::RemoteOperations` | ✅ `Git::Base` delegator added (PR 2d) |
386
+ | `diff_index(treeish)` | `Git::Repository::Diffing` | ✅ `Git::Base` delegator added (PR 2d) |
387
+ | `full_tree(sha)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added (PR 2d) |
388
+ | `name_rev(commit_ish)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added (PR 2d) |
389
+ | `stash_apply(id = nil)` | `Git::Repository::Stashing` | ✅ `Git::Base` delegator added (PR 2d) |
390
+ | `stash_clear` | `Git::Repository::Stashing` | ✅ `Git::Base` delegator added (PR 2d) |
391
+ | `stash_save(message)` | `Git::Repository::Stashing` | ✅ `Git::Base` delegator added (PR 2d) |
392
+ | `stashes_all` | `Git::Repository::Stashing` | ✅ `Git::Base` delegator added (PR 2d) |
393
+ | `tag_sha(tag_name)` | `Git::Repository::ObjectOperations` | ✅ `Git::Base` delegator added (PR 2d) |
394
+ | `untracked_files` | `Git::Repository::StatusOperations` | ✅ `Git::Base` delegator added (PR 2d) |
395
+ | `worktree_add(dir, commitish = nil)` | `Git::Repository::WorktreeOperations` | ✅ `Git::Base` delegator added (PR 2d) |
396
+ | `worktree_prune` | `Git::Repository::WorktreeOperations` | ✅ `Git::Base` delegator added (PR 2d) |
397
+ | `worktree_remove(dir)` | `Git::Repository::WorktreeOperations` | ✅ `Git::Base` delegator added (PR 2d) |
398
+ | `worktrees_all` | `Git::Repository::WorktreeOperations` | ✅ `Git::Base` delegator added (PR 2d) |
399
+
400
+ Also note name-mismatch cases where `Git::Lib` uses a different name than `Git::Repository`:
401
+
402
+ | `Git::Lib` method | `Git::Repository` equivalent | Action |
403
+ |-------------------|-------------------------------|--------|
404
+ | `conflicts` (yields file, your, their) | `Git::Repository::Merging#each_conflict` | ✅ deprecated `conflicts(&)` wrapper added to `Git::Repository::Merging` + `Git::Base` delegator added |
405
+ | `empty?` | `Git::Repository::StatusOperations#no_commits?` | ✅ deprecated `empty?` wrapper added to `Git::Repository::StatusOperations` + `Git::Base` delegator added |
406
+ | `remote_add(name, url, opts)` | `Git::Repository::RemoteOperations#remote_add` | ✅ `remote_add` is now the **canonical** method name in `Git::Repository::RemoteOperations`; `add_remote` kept as deprecated alias; `Git::Base` delegators for both names |
407
+ | `remote_remove(name)` | `Git::Repository::RemoteOperations#remote_remove` | ✅ `remote_remove` is now the **canonical** method name; `remove_remote` kept as deprecated alias; `Git::Base` delegators for both names |
408
+ | `remote_set_url(name, url, opts)` | `Git::Repository::RemoteOperations#remote_set_url` | ✅ `remote_set_url` is now the **canonical** method name; `set_remote_url` kept as deprecated alias; `Git::Base` delegators for both names |
409
+ | `namerev` (alias for `name_rev`) | `Git::Repository::ObjectOperations#name_rev` | ✅ `alias namerev name_rev` added (PR 2e) |
410
+ | `object_contents` (alias for `cat_file_contents`) | `Git::Repository::ObjectOperations#cat_file_contents` | ✅ `alias object_contents cat_file_contents` added (PR 2e) |
411
+ | `object_type` (alias for `cat_file_type`) | `Git::Repository::ObjectOperations#cat_file_type` | ✅ `alias object_type cat_file_type` added (PR 2e) |
412
+ | `object_size` (alias for `cat_file_size`) | `Git::Repository::ObjectOperations#cat_file_size` | ✅ `alias object_size cat_file_size` added (PR 2e) |
413
+ | `commit_data` (alias for `cat_file_commit`) | `Git::Repository::ObjectOperations#cat_file_commit` | ✅ `alias commit_data cat_file_commit` added (PR 2e) |
414
+ | `tag_data` (alias for `cat_file_tag`) | `Git::Repository::ObjectOperations#cat_file_tag` | ✅ `alias tag_data cat_file_tag` added (PR 2e) |
415
+ | `revparse` (alias for `rev_parse`) | (covered in Bucket 2) | ✅ covered |
416
+ | `branch_current` | `Git::Repository::Branching#current_branch` | ✅ `alias branch_current current_branch` added to `Git::Base` (name mismatch: `Git::Lib` defines `branch_current`; `Git::Repository` exposes `current_branch`) |
417
+
418
+ ### 7.3 Methods NOT Yet in `Git::Repository` (new facade work required)
419
+
420
+ These require a new facade method before a base.rb delegator can be added.
421
+
422
+ | `Git::Lib` method | Assessment | Recommended status |
423
+ |-------------------|------------|--------------------|
424
+ | `change_head_branch(branch_name)` | Low-level `git symbolic-ref HEAD refs/heads/<name>`; used internally for branch renaming and orphan checkout. Plausible external use by tooling. | ✅ promoted — facade in `Git::Repository::Branching` + `Git::Base` delegator added (PR 5h-1) |
425
+ | `config_get(name)` | Returns a single config value. Used by tooling. Part of the existing `config()` facade which reads/writes. | ✅ promoted as deprecated methods — forwarding wrappers in `Git::Repository::Configuring` + `Git::Base` delegators added (PR 5h-2); remove in v6.0.0 |
426
+ | `config_list` | Returns full config hash. Used by tooling. | ✅ promoted as deprecated methods — forwarding wrappers in `Git::Repository::Configuring` + `Git::Base` delegators added (PR 5h-2); remove in v6.0.0 |
427
+ | `config_set(name, value, options)` | Sets a config value. | ✅ promoted as deprecated methods — forwarding wrappers in `Git::Repository::Configuring` + `Git::Base` delegators added (PR 5h-2); remove in v6.0.0 |
428
+ | `global_config_get(name)` | Gets a global config value. | ✅ promoted — `global_config` facade + deprecated aliases in `Git::Repository::Configuring` + `Git::Base` delegators added (PR 5h-3) |
429
+ | `global_config_list` | Returns the full global config hash. | ✅ promoted — `global_config` facade + deprecated aliases in `Git::Repository::Configuring` + `Git::Base` delegators added (PR 5h-3) |
430
+ | `global_config_set(name, value)` | Sets a global config value. | ✅ promoted — `global_config` facade + deprecated aliases in `Git::Repository::Configuring` + `Git::Base` delegators added (PR 5h-3) |
431
+ | `git_version` | Returns `Git::Version` for the current binary. Useful for tooling that conditionally enables features. Not a repository concern; `Git.git_version` is the canonical API. | ✅ delegator added to `Git::Base` — delegates to `Git.git_version` |
432
+ | `list_files(ref_dir)` | Lists files under `.git/refs/{ref_dir}`. Internal ref-filesystem access. No plausible clean public use. | ❌ remove — internal plumbing; direct callers should migrate to `Git::Repository` ref-inspection methods |
433
+ | `ls_remote(location = nil, opts = {})` | Lists remote refs. Clearly useful externally. | ✅ promoted — facade in `Git::Repository::RemoteOperations` + `Git::Base` delegator added (PR 5f) |
434
+ | `mv(source, destination, options = {})` | Wraps `git mv`. Externally useful. | ✅ promoted — `Git::Repository::Staging#mv(source, destination, options = {})` added + `Git::Base` delegator added (PR 3) |
435
+ | `parse_config(file)` | Parses a config file from path. | ✅ promoted as deprecated method — `config()` extended with `:file` option for get/list overloads; deprecated `parse_config(file)` forwarding wrapper + `Git::Base` delegator added (PR 5h-4); remove in v6 |
436
+ | `stash_list` | Returns a formatted string `"stash@{0}: ...\n..."` — distinct from `stashes_all` which returns structured data. | ✅ promoted as deprecated method — `Git::Repository::Stashing#stash_list` + `Git::Base` delegator added (PR 5h-5); remove in v6 |
437
+ | `unmerged` | Returns paths with unresolved merge conflicts. Already partially covered by `each_conflict` (yields paths to temporary files for staged content). Pure path list is useful. | ✅ promoted — public method in `Git::Repository::Merging` + `Git::Base` delegator added (PR 5h-6) |
438
+ | `current_branch_state` | Returns a `HeadState` value object with `:state` (`:active`/`:unborn`/`:detached`) and `:name`. Richer than `current_branch`. Legacy `Git::Lib` implementation used a mutable `Struct`; promoted facade uses an immutable `Data` object. | ✅ promoted — `HeadState` Data object defined in `Git::Repository::Branching`; facade in `Git::Repository::Branching` + `Git::Base` delegator added (PR 5g) |
439
+
440
+ ### 7.4 Internal Plumbing — Mark as ❌ Remove
441
+
442
+ > ✅ **Completed** — `@api private` YARD tags added to all 12 methods listed below (commit `9c760a18`). These methods will be moved behind `private` or fully removed when `Git::Lib` is deleted in Phase 4.
443
+
444
+ These methods are technically public (defined before `private` in lib.rb) but are
445
+ clearly internal helpers with no plausible external use. They should appear in the
446
+ upgrade notes as "unsupported; remove any `g.lib.X` calls."
447
+
448
+ | Method | Reason |
449
+ |--------|--------|
450
+ | `assert_args_are_not_options(arg_name, *args)` | Input validation helper |
451
+ | `assert_valid_opts(opts, allowed)` | Option validation helper |
452
+ | `cat_file_object_meta(object)` | Internal batch cat-file helper |
453
+ | `command_capturing(*, **options_hash)` | Low-level command execution infrastructure |
454
+ | `command_streaming(*, **options_hash)` | Low-level command execution infrastructure |
455
+ | `each_cat_file_header(data)` | Parsing helper |
456
+ | `handle_deprecated_path_option(opts)` | Deprecation handling helper |
457
+ | `normalize_pathspecs(pathspecs, arg_name)` | Input normalization helper |
458
+ | `parse_cat_file_meta(output, object)` | Parsing helper |
459
+ | `parse_config_list(lines)` | Internal config parsing helper |
460
+ | `process_commit_data(data, sha)` | Parsing helper (used by `cat_file_commit`) |
461
+ | `validate_pathspec_types(pathspecs, arg_name)` | Input validation helper |
462
+
463
+ ### 7.5 Bucket 6 Count Summary
464
+
465
+ | Status | Count |
466
+ |--------|-------|
467
+ | ✅ promote (facade + `Git::Base` delegator added, or alias — PR 2d/2e/3/5g/5h series) | 36 |
468
+ | ⬜ promote (new facade work required) | 0 |
469
+ | ❌ remove (internal plumbing) | 12 |
470
+ | 🔍 human decision | 0 |
471
+ | **Total orphaned methods** | **48** |
472
+
473
+ > ✅ **All promotions complete.** All 36 promotable methods (§7.2 trivial wiring
474
+ > + name-mismatch cases, §7.3 new-facade methods) have been merged (PR
475
+ > 2d/2e/3/5f/5g/5h series). The 12 internal plumbing methods are annotated
476
+ > `@api private` (§7.4). No further action required for Bucket 6.
477
+
478
+ ---
479
+
480
+ ## 8. Recommended PR Split for Remediation
481
+
482
+ ### PR 2 — Aliases / Wrappers (Bucket 2 + Bucket 6 trivial wiring) ✅ Complete
483
+
484
+ **Scope:**
485
+ - Add aliases `remove`, `revparse` to the corresponding
486
+ `Git::Repository` modules (2 trivial changes; `diff_name_status` is already
487
+ aliased in `Git::Repository::Diffing` and requires no further action).
488
+ - Add deprecated wrapper `reset_hard` to `Git::Repository::Staging` (calls
489
+ `reset` with `hard: true`; `@deprecated` tag already present in `Git::Base`).
490
+ - Add deprecated stubs `is_branch?`, `is_local_branch?`, `is_remote_branch?`
491
+ to `Git::Repository::Branching`; add missing YARD `@deprecated` tags to all
492
+ three in both `Git::Base` and the new stubs.
493
+ - Batch-add `Git::Base` delegators for the 24 Bucket 6 "trivial wiring" orphans
494
+ from §7.2 that already have a `Git::Repository` home.
495
+ - Add legacy aliases to `Git::Repository::ObjectOperations` for `namerev`,
496
+ `object_contents`, `object_type`, `object_size`, `commit_data`, `tag_data`.
497
+
498
+ **Dependency:** None — can be merged first.
499
+
500
+ **Effort:** Small (mostly one-line additions, no new command classes or parsers).
501
+
502
+ ### PR 3 — Low-Level Methods (Bucket 3) ✅ Complete
503
+
504
+ **Scope:**
505
+ - Implement facade methods for `describe`, `repack`, `gc`, `apply`, `apply_mail`,
506
+ `read_tree` in `Git::Repository`.
507
+ - Create a new `Git::Repository::Maintenance` module for `repack` and `gc`.
508
+ - Add `Git::Base` delegators for all six methods.
509
+ - Resolve `cat_file` per the human decision in §6.
510
+ - Add facade methods for `mv`, `ls_remote`, `current_branch_state`
511
+ from Bucket 6 §7.3 (new facade work needed).
512
+
513
+ **Dependency:** PR 3 is independent of PR 2 but should be merged after PR 2
514
+ to keep the base.rb delegator surface tidy.
515
+
516
+ **Effort:** Moderate (6 facade methods + 4 new bucket-6 facades + optional new module).
517
+
518
+ ### PR 4 — Signature Sweep (Bucket 5) ✅ Complete
519
+
520
+ **Scope:**
521
+ - Fix 6 `⚠️` signatures:
522
+ - `checkout` in `Git::Repository::Branching`: change `(branch = nil, options = {})` → `(*args, **kwargs)` and unpack into named locals; preserve all internal validation logic
523
+ - `reset` in `Git::Repository::Staging`: change `**)` → `opts = {})`
524
+ - `commit` in `Git::Repository::Committing`: change `(message = nil, **opts)` → `(message, opts = {})`
525
+ - `commit_all` in `Git::Repository::Committing`: change `(*, **)` → `(message, opts = {})`
526
+ - `commit_tree` in `Git::Repository::Committing`: change `(tree, **opts)` → `(tree = nil, opts = {})`
527
+ - `write_and_commit_tree` in `Git::Repository::Committing`: change `(**)` → `(opts = {})`
528
+ (`add` is already aligned with `Git::Base` and requires no change.)
529
+ - Resolve human decision for `fsck` classification.
530
+
531
+ **Dependency:** PR 4 can be merged in any order relative to PR 2 and PR 3,
532
+ **but must be merged before** `Git.open`/`.clone`/`.init`/`.bare` are changed
533
+ to return `Git::Repository` directly — the signature fixes prevent Ruby 3
534
+ `ArgumentError` regressions for callers who pass a positional `Hash` variable
535
+ to `reset`, `commit`, `commit_all`, `commit_tree`, or `write_and_commit_tree`,
536
+ and prevent call-shape regressions for `checkout`. (`add` is exempt: both
537
+ `Git::Base#add` and `Git::Repository::Staging#add` already use `**`.)
538
+
539
+ **Effort:** Small (signature changes only; no new logic). Tests for the
540
+ legacy call shapes must be added or verified.
541
+
542
+ ### PR 5 — Bucket 6 Companion Document + Remaining Promotions ✅ Complete
543
+
544
+ **Scope:**
545
+ - Author `redesign/c1c2_bucket6_lib_orphans.md` to capture the full Bucket 6
546
+ analysis for the 16 human-decision items and the 7 new-facade-required items.
547
+ - Implement the 7 new facade promotions once human decisions are resolved.
548
+ - Mark the 12 internal plumbing methods as `@api private` or move them behind
549
+ `private` in `Git::Lib` as a preparatory step for Phase 4 deletion.
550
+
551
+ **Dependency:** PR 5 depends on PR 2 (trivial wiring PR sets the delegation
552
+ baseline), and on the companion document review for the 16 human-decision items.
553
+
554
+ **Effort:** Moderate-to-large; primarily gated on human decisions.
555
+
556
+ ### Dependency Graph
557
+
558
+ ```
559
+ PR 2 (aliases + trivial wiring)
560
+ └─→ PR 3 (low-level facades) ──┐
561
+ └─→ PR 4 (signature sweep) ────┤──→ Phase C1d (switch Git.open to return Git::Repository)
562
+ PR 5 (bucket-6 companion + new facades) (can proceed in parallel with PR 3/4)
563
+ ```
564
+
565
+ No circular dependencies. PR 2 unblocks everything else and should be merged
566
+ first.