git 4.3.2 → 5.0.0.beta.1

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 (280) hide show
  1. checksums.yaml +4 -4
  2. data/.github/copilot-instructions.md +67 -2705
  3. data/.github/pull_request_template.md +3 -1
  4. data/.github/skills/breaking-change-analysis/SKILL.md +102 -0
  5. data/.github/skills/ci-cd-troubleshooting/SKILL.md +264 -0
  6. data/.github/skills/command-implementation/REFERENCE.md +993 -0
  7. data/.github/skills/command-implementation/SKILL.md +229 -0
  8. data/.github/skills/command-test-conventions/SKILL.md +660 -0
  9. data/.github/skills/command-yard-documentation/SKILL.md +426 -0
  10. data/.github/skills/dependency-management/SKILL.md +72 -0
  11. data/.github/skills/development-workflow/SKILL.md +506 -0
  12. data/.github/skills/extract-command-from-lib/SKILL.md +487 -0
  13. data/.github/skills/extract-facade-from-base-lib/SKILL.md +586 -0
  14. data/.github/skills/facade-implementation/REFERENCE.md +840 -0
  15. data/.github/skills/facade-implementation/SKILL.md +260 -0
  16. data/.github/skills/facade-test-conventions/SKILL.md +380 -0
  17. data/.github/skills/facade-yard-documentation/SKILL.md +429 -0
  18. data/.github/skills/make-skill-template/SKILL.md +176 -0
  19. data/.github/skills/pr-readiness-review/SKILL.md +185 -0
  20. data/.github/skills/project-context/SKILL.md +313 -0
  21. data/.github/skills/pull-request-review/SKILL.md +168 -0
  22. data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +131 -0
  23. data/.github/skills/release-management/SKILL.md +125 -0
  24. data/.github/skills/review-arguments-dsl/CHECKLIST.md +788 -0
  25. data/.github/skills/review-arguments-dsl/SKILL.md +214 -0
  26. data/.github/skills/review-backward-compatibility/SKILL.md +275 -0
  27. data/.github/skills/review-cross-command-consistency/SKILL.md +139 -0
  28. data/.github/skills/reviewing-skills/SKILL.md +189 -0
  29. data/.github/skills/rspec-unit-testing-standards/SKILL.md +639 -0
  30. data/.github/skills/tdd-refactor-step/SKILL.md +236 -0
  31. data/.github/skills/test-debugging/SKILL.md +160 -0
  32. data/.github/skills/yard-documentation/SKILL.md +793 -0
  33. data/.github/workflows/continuous_integration.yml +3 -2
  34. data/.github/workflows/enforce_conventional_commits.yml +1 -1
  35. data/.github/workflows/experimental_continuous_integration.yml +2 -2
  36. data/.github/workflows/release.yml +3 -4
  37. data/.gitignore +8 -0
  38. data/.husky/pre-commit +13 -0
  39. data/.release-please-manifest.json +1 -1
  40. data/.rspec +3 -0
  41. data/.rubocop.yml +7 -3
  42. data/.rubocop_todo.yml +23 -5
  43. data/.yardopts +1 -0
  44. data/CHANGELOG.md +0 -40
  45. data/CONTRIBUTING.md +694 -53
  46. data/README.md +17 -5
  47. data/Rakefile +61 -9
  48. data/commitlint.test +4 -0
  49. data/git.gemspec +14 -8
  50. data/lib/git/args_builder.rb +0 -8
  51. data/lib/git/base.rb +486 -410
  52. data/lib/git/branch.rb +380 -43
  53. data/lib/git/branch_delete_failure.rb +31 -0
  54. data/lib/git/branch_delete_result.rb +63 -0
  55. data/lib/git/branch_info.rb +178 -0
  56. data/lib/git/branches.rb +130 -24
  57. data/lib/git/command_line/base.rb +245 -0
  58. data/lib/git/command_line/capturing.rb +249 -0
  59. data/lib/git/command_line/result.rb +96 -0
  60. data/lib/git/command_line/streaming.rb +194 -0
  61. data/lib/git/command_line.rb +43 -322
  62. data/lib/git/command_line_result.rb +4 -88
  63. data/lib/git/commands/add.rb +131 -0
  64. data/lib/git/commands/am/abort.rb +43 -0
  65. data/lib/git/commands/am/apply.rb +252 -0
  66. data/lib/git/commands/am/continue.rb +43 -0
  67. data/lib/git/commands/am/quit.rb +43 -0
  68. data/lib/git/commands/am/retry.rb +47 -0
  69. data/lib/git/commands/am/show_current_patch.rb +64 -0
  70. data/lib/git/commands/am/skip.rb +42 -0
  71. data/lib/git/commands/am.rb +33 -0
  72. data/lib/git/commands/apply.rb +237 -0
  73. data/lib/git/commands/archive/list_formats.rb +46 -0
  74. data/lib/git/commands/archive.rb +140 -0
  75. data/lib/git/commands/arguments.rb +3510 -0
  76. data/lib/git/commands/base.rb +403 -0
  77. data/lib/git/commands/branch/copy.rb +94 -0
  78. data/lib/git/commands/branch/create.rb +173 -0
  79. data/lib/git/commands/branch/delete.rb +80 -0
  80. data/lib/git/commands/branch/list.rb +162 -0
  81. data/lib/git/commands/branch/move.rb +94 -0
  82. data/lib/git/commands/branch/set_upstream.rb +86 -0
  83. data/lib/git/commands/branch/show_current.rb +49 -0
  84. data/lib/git/commands/branch/unset_upstream.rb +57 -0
  85. data/lib/git/commands/branch.rb +34 -0
  86. data/lib/git/commands/cat_file/batch.rb +364 -0
  87. data/lib/git/commands/cat_file/filtered.rb +105 -0
  88. data/lib/git/commands/cat_file/raw.rb +210 -0
  89. data/lib/git/commands/cat_file.rb +49 -0
  90. data/lib/git/commands/checkout/branch.rb +151 -0
  91. data/lib/git/commands/checkout/files.rb +115 -0
  92. data/lib/git/commands/checkout.rb +38 -0
  93. data/lib/git/commands/checkout_index.rb +105 -0
  94. data/lib/git/commands/clean.rb +100 -0
  95. data/lib/git/commands/clone.rb +240 -0
  96. data/lib/git/commands/commit.rb +272 -0
  97. data/lib/git/commands/commit_tree.rb +100 -0
  98. data/lib/git/commands/config_option_syntax/add.rb +83 -0
  99. data/lib/git/commands/config_option_syntax/get.rb +117 -0
  100. data/lib/git/commands/config_option_syntax/get_all.rb +115 -0
  101. data/lib/git/commands/config_option_syntax/get_color.rb +91 -0
  102. data/lib/git/commands/config_option_syntax/get_color_bool.rb +93 -0
  103. data/lib/git/commands/config_option_syntax/get_regexp.rb +115 -0
  104. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +102 -0
  105. data/lib/git/commands/config_option_syntax/list.rb +107 -0
  106. data/lib/git/commands/config_option_syntax/remove_section.rb +74 -0
  107. data/lib/git/commands/config_option_syntax/rename_section.rb +78 -0
  108. data/lib/git/commands/config_option_syntax/replace_all.rb +104 -0
  109. data/lib/git/commands/config_option_syntax/set.rb +114 -0
  110. data/lib/git/commands/config_option_syntax/unset.rb +89 -0
  111. data/lib/git/commands/config_option_syntax/unset_all.rb +89 -0
  112. data/lib/git/commands/config_option_syntax.rb +56 -0
  113. data/lib/git/commands/describe.rb +155 -0
  114. data/lib/git/commands/diff.rb +656 -0
  115. data/lib/git/commands/diff_files.rb +518 -0
  116. data/lib/git/commands/diff_index.rb +496 -0
  117. data/lib/git/commands/fetch.rb +352 -0
  118. data/lib/git/commands/fsck.rb +136 -0
  119. data/lib/git/commands/gc.rb +132 -0
  120. data/lib/git/commands/grep.rb +338 -0
  121. data/lib/git/commands/init.rb +99 -0
  122. data/lib/git/commands/log.rb +632 -0
  123. data/lib/git/commands/ls_files.rb +191 -0
  124. data/lib/git/commands/ls_remote.rb +155 -0
  125. data/lib/git/commands/ls_tree.rb +131 -0
  126. data/lib/git/commands/maintenance/register.rb +75 -0
  127. data/lib/git/commands/maintenance/run.rb +104 -0
  128. data/lib/git/commands/maintenance/start.rb +66 -0
  129. data/lib/git/commands/maintenance/stop.rb +55 -0
  130. data/lib/git/commands/maintenance/unregister.rb +79 -0
  131. data/lib/git/commands/maintenance.rb +31 -0
  132. data/lib/git/commands/merge/abort.rb +44 -0
  133. data/lib/git/commands/merge/continue.rb +44 -0
  134. data/lib/git/commands/merge/quit.rb +46 -0
  135. data/lib/git/commands/merge/start.rb +245 -0
  136. data/lib/git/commands/merge.rb +28 -0
  137. data/lib/git/commands/merge_base.rb +86 -0
  138. data/lib/git/commands/mv.rb +77 -0
  139. data/lib/git/commands/name_rev.rb +114 -0
  140. data/lib/git/commands/pull.rb +377 -0
  141. data/lib/git/commands/push.rb +246 -0
  142. data/lib/git/commands/read_tree.rb +149 -0
  143. data/lib/git/commands/remote/add.rb +91 -0
  144. data/lib/git/commands/remote/get_url.rb +66 -0
  145. data/lib/git/commands/remote/list.rb +54 -0
  146. data/lib/git/commands/remote/prune.rb +61 -0
  147. data/lib/git/commands/remote/remove.rb +52 -0
  148. data/lib/git/commands/remote/rename.rb +69 -0
  149. data/lib/git/commands/remote/set_branches.rb +63 -0
  150. data/lib/git/commands/remote/set_head.rb +82 -0
  151. data/lib/git/commands/remote/set_url.rb +71 -0
  152. data/lib/git/commands/remote/set_url_add.rb +61 -0
  153. data/lib/git/commands/remote/set_url_delete.rb +64 -0
  154. data/lib/git/commands/remote/show.rb +71 -0
  155. data/lib/git/commands/remote/update.rb +72 -0
  156. data/lib/git/commands/remote.rb +42 -0
  157. data/lib/git/commands/repack.rb +277 -0
  158. data/lib/git/commands/reset.rb +147 -0
  159. data/lib/git/commands/rev_parse.rb +297 -0
  160. data/lib/git/commands/revert/abort.rb +45 -0
  161. data/lib/git/commands/revert/continue.rb +57 -0
  162. data/lib/git/commands/revert/quit.rb +47 -0
  163. data/lib/git/commands/revert/skip.rb +44 -0
  164. data/lib/git/commands/revert/start.rb +153 -0
  165. data/lib/git/commands/revert.rb +29 -0
  166. data/lib/git/commands/rm.rb +114 -0
  167. data/lib/git/commands/show.rb +632 -0
  168. data/lib/git/commands/show_ref/exclude_existing.rb +120 -0
  169. data/lib/git/commands/show_ref/exists.rb +78 -0
  170. data/lib/git/commands/show_ref/list.rb +145 -0
  171. data/lib/git/commands/show_ref/verify.rb +120 -0
  172. data/lib/git/commands/show_ref.rb +42 -0
  173. data/lib/git/commands/stash/apply.rb +75 -0
  174. data/lib/git/commands/stash/branch.rb +65 -0
  175. data/lib/git/commands/stash/clear.rb +41 -0
  176. data/lib/git/commands/stash/create.rb +58 -0
  177. data/lib/git/commands/stash/drop.rb +67 -0
  178. data/lib/git/commands/stash/list.rb +39 -0
  179. data/lib/git/commands/stash/pop.rb +78 -0
  180. data/lib/git/commands/stash/push.rb +103 -0
  181. data/lib/git/commands/stash/show.rb +149 -0
  182. data/lib/git/commands/stash/store.rb +63 -0
  183. data/lib/git/commands/stash.rb +38 -0
  184. data/lib/git/commands/status.rb +169 -0
  185. data/lib/git/commands/symbolic_ref/delete.rb +68 -0
  186. data/lib/git/commands/symbolic_ref/read.rb +95 -0
  187. data/lib/git/commands/symbolic_ref/update.rb +76 -0
  188. data/lib/git/commands/symbolic_ref.rb +38 -0
  189. data/lib/git/commands/tag/create.rb +139 -0
  190. data/lib/git/commands/tag/delete.rb +55 -0
  191. data/lib/git/commands/tag/list.rb +143 -0
  192. data/lib/git/commands/tag/verify.rb +71 -0
  193. data/lib/git/commands/tag.rb +26 -0
  194. data/lib/git/commands/update_ref/batch.rb +140 -0
  195. data/lib/git/commands/update_ref/delete.rb +92 -0
  196. data/lib/git/commands/update_ref/update.rb +106 -0
  197. data/lib/git/commands/update_ref.rb +42 -0
  198. data/lib/git/commands/version.rb +52 -0
  199. data/lib/git/commands/worktree/add.rb +140 -0
  200. data/lib/git/commands/worktree/list.rb +64 -0
  201. data/lib/git/commands/worktree/lock.rb +58 -0
  202. data/lib/git/commands/worktree/management_base.rb +51 -0
  203. data/lib/git/commands/worktree/move.rb +66 -0
  204. data/lib/git/commands/worktree/prune.rb +67 -0
  205. data/lib/git/commands/worktree/remove.rb +63 -0
  206. data/lib/git/commands/worktree/repair.rb +76 -0
  207. data/lib/git/commands/worktree/unlock.rb +47 -0
  208. data/lib/git/commands/worktree.rb +43 -0
  209. data/lib/git/commands/write_tree.rb +68 -0
  210. data/lib/git/commands.rb +89 -0
  211. data/lib/git/detached_head_info.rb +54 -0
  212. data/lib/git/diff.rb +297 -7
  213. data/lib/git/diff_file_numstat_info.rb +29 -0
  214. data/lib/git/diff_file_patch_info.rb +134 -0
  215. data/lib/git/diff_file_raw_info.rb +127 -0
  216. data/lib/git/diff_info.rb +169 -0
  217. data/lib/git/diff_path_status.rb +78 -19
  218. data/lib/git/diff_result.rb +32 -0
  219. data/lib/git/diff_stats.rb +59 -14
  220. data/lib/git/dirstat_info.rb +86 -0
  221. data/lib/git/errors.rb +65 -2
  222. data/lib/git/execution_context/global.rb +56 -0
  223. data/lib/git/execution_context/repository.rb +147 -0
  224. data/lib/git/execution_context.rb +482 -0
  225. data/lib/git/file_ref.rb +74 -0
  226. data/lib/git/fsck_object.rb +9 -9
  227. data/lib/git/fsck_result.rb +1 -1
  228. data/lib/git/lib.rb +1606 -1028
  229. data/lib/git/log.rb +15 -2
  230. data/lib/git/object.rb +92 -22
  231. data/lib/git/parsers/branch.rb +224 -0
  232. data/lib/git/parsers/cat_file.rb +111 -0
  233. data/lib/git/parsers/diff.rb +585 -0
  234. data/lib/git/parsers/fsck.rb +133 -0
  235. data/lib/git/parsers/grep.rb +42 -0
  236. data/lib/git/parsers/ls_tree.rb +58 -0
  237. data/lib/git/parsers/stash.rb +208 -0
  238. data/lib/git/parsers/tag.rb +257 -0
  239. data/lib/git/remote.rb +133 -9
  240. data/lib/git/repository/branching.rb +572 -0
  241. data/lib/git/repository/committing.rb +191 -0
  242. data/lib/git/repository/configuring.rb +156 -0
  243. data/lib/git/repository/diffing.rb +775 -0
  244. data/lib/git/repository/inspecting.rb +153 -0
  245. data/lib/git/repository/logging.rb +247 -0
  246. data/lib/git/repository/merging.rb +295 -0
  247. data/lib/git/repository/object_operations.rb +1101 -0
  248. data/lib/git/repository/path_resolver.rb +207 -0
  249. data/lib/git/repository/remote_operations.rb +753 -0
  250. data/lib/git/repository/shared_private.rb +51 -0
  251. data/lib/git/repository/staging.rb +390 -0
  252. data/lib/git/repository/stashing.rb +107 -0
  253. data/lib/git/repository/status_operations.rb +180 -0
  254. data/lib/git/repository/worktree_operations.rb +159 -0
  255. data/lib/git/repository.rb +264 -1
  256. data/lib/git/stash.rb +85 -4
  257. data/lib/git/stash_info.rb +104 -0
  258. data/lib/git/stashes.rb +130 -13
  259. data/lib/git/status.rb +224 -18
  260. data/lib/git/tag_delete_failure.rb +31 -0
  261. data/lib/git/tag_delete_result.rb +63 -0
  262. data/lib/git/tag_info.rb +105 -0
  263. data/lib/git/version.rb +109 -2
  264. data/lib/git/version_constraint.rb +81 -0
  265. data/lib/git/worktree.rb +120 -5
  266. data/lib/git/worktrees.rb +107 -7
  267. data/lib/git.rb +114 -18
  268. data/redesign/1_architecture_existing.md +54 -18
  269. data/redesign/2_architecture_redesign.md +365 -46
  270. data/redesign/3_architecture_implementation.md +1451 -54
  271. data/tasks/gem_tasks.rake +4 -0
  272. data/tasks/npm_tasks.rake +7 -0
  273. data/tasks/rspec.rake +48 -0
  274. data/tasks/test.rake +13 -1
  275. data/tasks/yard.rake +34 -7
  276. metadata +349 -20
  277. data/lib/git/index.rb +0 -6
  278. data/lib/git/path.rb +0 -38
  279. data/lib/git/working_directory.rb +0 -6
  280. /data/{release-please-config.json → .release-please-config.json} +0 -0
@@ -0,0 +1,236 @@
1
+ ---
2
+ name: tdd-refactor-step
3
+ description: 'Guides the REFACTOR step of the TDD cycle — identifying code smells, applying safe refactoring techniques, cleaning test code, and verifying with rubocop. Use during RED-GREEN-REFACTOR when deciding what and how to refactor after making a test pass.'
4
+ ---
5
+
6
+ # TDD Refactor Step
7
+
8
+ Concrete guidance for the REFACTOR step of the RED-GREEN-REFACTOR cycle. Covers
9
+ code smells to look for, safe refactoring techniques, test code cleanup,
10
+ rubocop integration, and verification.
11
+
12
+ ## Contents
13
+
14
+ - [How to use this skill](#how-to-use-this-skill)
15
+ - [Related skills](#related-skills)
16
+ - [Decision: refactor or skip](#decision-refactor-or-skip)
17
+ - [Code smells checklist](#code-smells-checklist)
18
+ - [Refactoring techniques](#refactoring-techniques)
19
+ - [Test code refactoring](#test-code-refactoring)
20
+ - [Rubocop integration](#rubocop-integration)
21
+ - [Verification](#verification)
22
+ - [Project-specific patterns](#project-specific-patterns)
23
+ - [Boundaries](#boundaries)
24
+
25
+ ## How to use this skill
26
+
27
+ Invoke this skill during the REFACTOR step of the TDD cycle, after GREEN
28
+ (all tests pass). This skill expands the guidance in the
29
+ [Development Workflow](../development-workflow/SKILL.md) REFACTOR step.
30
+
31
+ Typical invocation:
32
+
33
+ ```text
34
+ I just got to green. Walk me through the REFACTOR step using
35
+ the TDD Refactor Step skill.
36
+ ```
37
+
38
+ ## Related skills
39
+
40
+ - [Development Workflow](../development-workflow/SKILL.md) — parent TDD workflow;
41
+ this skill supplements its REFACTOR step
42
+ - [RSpec Unit Testing Standards](../rspec-unit-testing-standards/SKILL.md) — test
43
+ conventions that refactored tests must follow
44
+ - [PR Readiness Review](../pr-readiness-review/SKILL.md) — final quality gate
45
+ that catches remaining quality issues
46
+
47
+ ## Decision: refactor or skip
48
+
49
+ Not every GREEN step needs refactoring. Skip when **all** of the following are true:
50
+
51
+ - No hardcoded values from the GREEN step remain
52
+ - No duplication was introduced between new and existing code
53
+ - No method exceeds ~10 lines
54
+ - No parameter list exceeds 3 positional parameters
55
+ - Rubocop reports no new offenses on changed files
56
+ - Test setup is not duplicated across examples
57
+
58
+ If any condition is false, proceed with the relevant technique below.
59
+
60
+ ## Code smells checklist
61
+
62
+ Check the code written or modified in this task for these smells, in priority order:
63
+
64
+ | # | Smell | Threshold | Action |
65
+ | --- | ----- | --------- | ------ |
66
+ | 1 | **Hardcoded values** from GREEN step | Any | Generalize to actual logic |
67
+ | 2 | **Duplication** between new code and existing code | ≥ 3 similar lines | Extract shared method or constant |
68
+ | 3 | **Long method** | > 10 lines (body) | Extract private helper |
69
+ | 4 | **Long parameter list** | > 3 positional params | Convert trailing params to keyword arguments |
70
+ | 5 | **Inconsistent naming** | Deviates from file/module conventions | Rename to match existing patterns |
71
+ | 6 | **Deeply nested conditionals** | > 2 levels | Extract guard clause or helper |
72
+ | 7 | **Feature envy** | Method uses another object's data more than its own | Move method or extract delegator |
73
+ | 8 | **Dead code** | Unreachable branches, unused variables | Remove |
74
+
75
+ Limit yourself to smells **in files you touched this task**. Broader cleanup belongs
76
+ in a separate task (add it during REPLAN).
77
+
78
+ ## Refactoring techniques
79
+
80
+ Apply the simplest technique that resolves the smell:
81
+
82
+ ### Extract method
83
+
84
+ Split a long method into a public method and one or more private helpers. Name
85
+ the helper after **what** it does, not **how**:
86
+
87
+ ```ruby
88
+ # Before
89
+ def call(*, **)
90
+ bound = args_definition.bind(*, **)
91
+ objects = Array(bound.objects).map { |o| "#{o}\n" }.join
92
+ with_stdin(objects) { |r| run_batch(bound, r) }
93
+ end
94
+
95
+ # After
96
+ def call(*, **)
97
+ bound = args_definition.bind(*, **)
98
+ with_stdin(stdin_content(bound)) { |r| run_batch(bound, r) }
99
+ end
100
+
101
+ private
102
+
103
+ def stdin_content(bound)
104
+ Array(bound.objects).map { |o| "#{o}\n" }.join
105
+ end
106
+ ```
107
+
108
+ ### Convert positional to keyword arguments
109
+
110
+ When a method accumulates optional trailing positional parameters:
111
+
112
+ ```ruby
113
+ # Before
114
+ def initialize(args, options, positionals, exec_names = [], flags = [])
115
+
116
+ # After
117
+ def initialize(args, options, positionals, exec_names: [], flags: [])
118
+ ```
119
+
120
+ Update the single call site at the same time.
121
+
122
+ ### Replace conditional with guard clause
123
+
124
+ ```ruby
125
+ # Before
126
+ def validate(value)
127
+ if value
128
+ if value.is_a?(String)
129
+ process(value)
130
+ end
131
+ end
132
+ end
133
+
134
+ # After
135
+ def validate(value)
136
+ return unless value
137
+ return unless value.is_a?(String)
138
+
139
+ process(value)
140
+ end
141
+ ```
142
+
143
+ ### Introduce constant
144
+
145
+ When a magic value appears in logic:
146
+
147
+ ```ruby
148
+ # Before
149
+ raise error if version < Git::Version.parse('2.28.0')
150
+
151
+ # After
152
+ MINIMUM_GIT_VERSION = Git::Version.parse('2.28.0')
153
+ raise error if version < MINIMUM_GIT_VERSION
154
+ ```
155
+
156
+ ### Eliminate duplication with shared setup
157
+
158
+ When two methods share identical preamble or teardown, extract the shared part.
159
+ If the duplication is in tests, see Test Code Refactoring below.
160
+
161
+ ## Test code refactoring
162
+
163
+ Test code deserves the same refactoring attention as production code:
164
+
165
+ | Smell | Technique |
166
+ | ----- | --------- |
167
+ | Duplicated `let`/`before` across contexts | Move to nearest shared `describe` or `context` |
168
+ | Long example bodies (> 5 lines of setup) | Extract to `let` declarations or `before` block |
169
+ | Repeated literal values | Extract to `let` or constant at top of file |
170
+ | Identical examples across files | Extract to shared example group (`shared_examples`) |
171
+ | Unclear example descriptions | Rewrite to state expected behavior, not implementation |
172
+
173
+ Follow the [RSpec Unit Testing Standards](../rspec-unit-testing-standards/SKILL.md)
174
+ for the resulting test structure.
175
+
176
+ ## Rubocop integration
177
+
178
+ Run rubocop on changed files after refactoring:
179
+
180
+ ```bash
181
+ bundle exec rubocop $(git diff --name-only HEAD)
182
+ ```
183
+
184
+ Focus on:
185
+ - `Metrics/MethodLength` — methods over the configured limit
186
+ - `Metrics/ParameterLists` — too many parameters
187
+ - `Metrics/AbcSize` — complexity threshold
188
+ - `Style` cops — naming, formatting consistency
189
+
190
+ Auto-correct safe offenses when appropriate:
191
+
192
+ ```bash
193
+ bundle exec rubocop -a $(git diff --name-only HEAD)
194
+ ```
195
+
196
+ Do not auto-correct `Metrics` cops — those require structural changes (extract
197
+ method, split class), not formatting fixes.
198
+
199
+ ## Verification
200
+
201
+ After refactoring, confirm:
202
+
203
+ 1. **Tests still pass:** `bundle exec rspec <spec_file>` for the current task's
204
+ test file(s)
205
+ 2. **No new rubocop offenses:** `bundle exec rubocop $(git diff --name-only HEAD)`
206
+ 3. **Behavior unchanged:** No new test was added during REFACTOR — if you need
207
+ a new test, you skipped a RED step
208
+
209
+ If any test fails after refactoring, the refactoring changed behavior. Revert
210
+ and try a smaller change.
211
+
212
+ ## Project-specific patterns
213
+
214
+ Patterns specific to this codebase that the REFACTOR step should enforce:
215
+
216
+ - **Command classes** should not contain parsing logic — if refactoring reveals
217
+ parsing in a command class, flag it for extraction (separate task)
218
+ - **Arguments DSL** `Bound` metadata uses keyword arguments — if adding new
219
+ metadata fields, follow the keyword argument pattern
220
+ - **Error classes** inherit from `Git::Error` — ensure new errors follow the
221
+ hierarchy in `lib/git/errors.rb`
222
+ - **`freeze` constants** — all new constants should be frozen
223
+ (`CONSTANT = value.freeze`)
224
+ - **Private methods** go below a single `private` keyword, not inline
225
+ `private def`
226
+
227
+ ## Boundaries
228
+
229
+ Things the REFACTOR step must **not** do:
230
+
231
+ - **Add new behavior** — no new features, no new test cases
232
+ - **Change public API** — method signatures visible to users stay the same
233
+ - **Touch unrelated files** — scope to files modified in this task; add broader
234
+ refactoring to the task list during REPLAN
235
+ - **Optimize prematurely** — clarity over performance unless profiling data exists
236
+ - **Over-abstract** — do not create a helper for something used exactly once
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: test-debugging
3
+ description: "Debugs failing or flaky tests and improves test coverage. Use when tests fail consistently, exhibit intermittent behavior, or when adding missing test coverage."
4
+ ---
5
+
6
+ # Test Debugging & Maintenance Workflow
7
+
8
+ When asked to debug tests or improve test coverage, follow this workflow to identify
9
+ problems, determine root causes, and apply appropriate fixes.
10
+
11
+ ## Contents
12
+
13
+ - [How to use this skill](#how-to-use-this-skill)
14
+ - [Related skills](#related-skills)
15
+ - [Step 1: Run and Observe the Test](#step-1-run-and-observe-the-test)
16
+ - [Step 2: Investigate Root Cause](#step-2-investigate-root-cause)
17
+ - [Step 3: Report Findings](#step-3-report-findings)
18
+ - [Step 4: Determine Fix Strategy](#step-4-determine-fix-strategy)
19
+ - [Step 5: Verify Test Fix](#step-5-verify-test-fix)
20
+ - [Project-Specific Considerations](#project-specific-considerations)
21
+
22
+ ## How to use this skill
23
+
24
+ Attach this file to your Copilot Chat context, then invoke it with the failing
25
+ test file, test name, or flakiness symptom. Stop at Step 3 for diagnosis-only
26
+ requests unless the user asks for implementation.
27
+
28
+ ## Related skills
29
+
30
+ - [RSpec Unit Testing Standards](../rspec-unit-testing-standards/SKILL.md) — rules
31
+ governing test isolation, determinism, and order independence (Rules 25–28); consult
32
+ when flakiness is caused by a test design violation rather than a production bug
33
+ - [Development Workflow](../development-workflow/SKILL.md) — required TDD process
34
+ when fixes involve production code
35
+ - [CI/CD Troubleshooting](../ci-cd-troubleshooting/SKILL.md) — investigate
36
+ failures that appear only in CI
37
+
38
+ ## Step 1: Run and Observe the Test
39
+
40
+ 1. **Run the failing test:**
41
+
42
+ ```bash
43
+ # TestUnit (legacy tests in tests/units/)
44
+ bundle exec bin/test <test_file_name>
45
+
46
+ # RSpec unit test
47
+ bundle exec rspec spec/unit/git/commands/<command>_spec.rb
48
+
49
+ # RSpec integration test
50
+ bundle exec rspec spec/integration/git/commands/<command>_spec.rb
51
+
52
+ # Specific test method (TestUnit)
53
+ bundle exec ruby -I lib:tests tests/units/test_base.rb -n test_method_name
54
+ ```
55
+
56
+ 2. **For suspected flaky tests, run multiple times:**
57
+
58
+ ```bash
59
+ for i in {1..20}; do
60
+ echo "Run $i"
61
+ bundle exec bin/test <test_file> || break
62
+ done
63
+ ```
64
+
65
+ 3. **Check test isolation** — run the test alone vs. within the full suite:
66
+
67
+ ```bash
68
+ bundle exec bin/test <test_file> # alone
69
+ bundle exec rake default # full suite
70
+ ```
71
+
72
+ ## Step 2: Investigate Root Cause
73
+
74
+ 1. **Read the full error** including stack trace. Identify exact failing line and
75
+ expected vs. actual values.
76
+
77
+ 2. **Check recent changes** with `git log` and `git blame` on the test file and
78
+ related production code.
79
+
80
+ 3. **For flaky tests**, look for:
81
+ - Shared state between tests (global/class variables, shared filesystem resources)
82
+ - Timing dependencies or race conditions
83
+ - Non-deterministic behavior (time-dependent logic, unordered iteration)
84
+ - Test execution order dependencies
85
+
86
+ 4. **For environment issues**, check:
87
+ - Platform differences (paths, line endings, permissions)
88
+ - Git version differences (use `git --version`)
89
+ - Ruby version differences
90
+
91
+ ## Step 3: Report Findings
92
+
93
+ Present diagnostic findings to the user:
94
+
95
+ ```markdown
96
+ # Test Failure Diagnosis: <test_name>
97
+
98
+ **Failure Type:** [Consistent / Flaky / Coverage Gap]
99
+ **Test File:** <path/to/test_file.rb>
100
+
101
+ ## Error
102
+ <error message and relevant stack trace>
103
+
104
+ ## Root Cause
105
+ <Explanation of why the test is failing>
106
+
107
+ ## Recommended Fix
108
+ <Specific recommendation>
109
+
110
+ **Would you like me to implement this fix?**
111
+ ```
112
+
113
+ **STOP here** unless the user asks you to proceed with the fix.
114
+
115
+ ## Step 4: Determine Fix Strategy
116
+
117
+ | Scenario | Strategy | Commit Type |
118
+ | --- | --- | --- |
119
+ | **Production code bug** (test caught a real bug) | Fix production code using the development-workflow TDD process. The failing test is the RED step. | `fix(component): <description>` |
120
+ | **Test needs updating** (intentional API change) | Get user confirmation first. Update test assertions. | `test(component): update test for <change>` |
121
+ | **Flaky test** (non-determinism) | Make test deterministic. Run 20+ times to verify. | `test(component): fix flaky test in <test_name>` |
122
+ | **Missing test coverage** | Add tests using the development-workflow TDD process. | `test(component): add tests for <feature>` |
123
+ | **Test refactoring** | Improve readability/reduce duplication. Keep tests green. | `refactor(test): improve <test_name>` |
124
+ | **Environment/setup issue** | Fix environment, document requirements. No code commit needed. | — |
125
+
126
+ **CRITICAL:** Get user confirmation before modifying existing tests.
127
+
128
+ ## Step 5: Verify Test Fix
129
+
130
+ ```bash
131
+ # Run the specific test
132
+ bundle exec bin/test <test_file> # TestUnit
133
+ bundle exec rspec <spec_file> # RSpec
134
+
135
+ # For flaky test fixes, run many times
136
+ for i in {1..50}; do
137
+ echo "Run $i"
138
+ bundle exec bin/test <test_file> || break
139
+ done
140
+
141
+ # Run full suite
142
+ bundle exec rake default
143
+ ```
144
+
145
+ ## Project-Specific Considerations
146
+
147
+ **Test frameworks:** This project uses both TestUnit (legacy tests in `tests/units/`)
148
+ and RSpec (new tests in `spec/`). Run both when verifying changes.
149
+
150
+ **Test helpers:** Use `clone_working_repo`, `create_temp_repo`, `in_temp_dir` from
151
+ test helpers for TestUnit. Use `include_context` shared contexts for RSpec.
152
+
153
+ **Mocking:** The project uses Mocha for TestUnit mocking and RSpec doubles for RSpec.
154
+ Be careful with stubs — they can mask real issues.
155
+
156
+ **Test data:** Fixtures are in `tests/files/`. Use test helpers to create temporary
157
+ repos. Clean up in teardown.
158
+
159
+ **CI vs. local differences:** If tests pass locally but fail in CI, use the
160
+ ci-cd-troubleshooting skill.