git 5.0.0.beta.3 → 5.0.0.beta.4

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 (268) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +27 -0
  3. data/.github/copilot-instructions.md +3 -8
  4. data/.github/hooks/bin-setup-on-worktree.json +11 -0
  5. data/.github/hooks/run-bin-setup-once.sh +14 -0
  6. data/.github/skills/breaking-change-analysis/SKILL.md +6 -9
  7. data/.github/skills/ci-cd-troubleshooting/SKILL.md +2 -2
  8. data/.github/skills/command-implementation/REFERENCE.md +34 -33
  9. data/.github/skills/command-implementation/SKILL.md +5 -4
  10. data/.github/skills/command-test-conventions/SKILL.md +13 -9
  11. data/.github/skills/command-yard-documentation/SKILL.md +14 -6
  12. data/.github/skills/development-workflow/SKILL.md +20 -14
  13. data/.github/skills/facade-implementation/REFERENCE.md +19 -22
  14. data/.github/skills/facade-implementation/SKILL.md +0 -5
  15. data/.github/skills/facade-test-conventions/SKILL.md +4 -7
  16. data/.github/skills/facade-yard-documentation/SKILL.md +8 -2
  17. data/.github/skills/make-skill-template/SKILL.md +53 -3
  18. data/.github/skills/pr-readiness-review/SKILL.md +22 -2
  19. data/.github/skills/project-context/SKILL.md +16 -23
  20. data/.github/skills/pull-request-review/SKILL.md +2 -2
  21. data/.github/skills/rebase/SKILL.md +148 -0
  22. data/.github/skills/refactor-command-to-commandlineresult/SKILL.md +1 -1
  23. data/.github/skills/resolve-feedback/SKILL.md +288 -0
  24. data/.github/skills/review-arguments-dsl/CHECKLIST.md +3 -3
  25. data/.github/skills/reviewing-skills/SKILL.md +28 -3
  26. data/.github/skills/test-debugging/SKILL.md +20 -19
  27. data/.github/skills/yard-documentation/SKILL.md +671 -483
  28. data/.github/skills/yard-documentation/element-rules.md +162 -0
  29. data/.github/skills-deprecated/README.md +21 -0
  30. data/.github/{skills → skills-deprecated}/extract-command-from-lib/SKILL.md +9 -9
  31. data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/SKILL.md +12 -12
  32. data/.github/workflows/continuous_integration.yml +3 -2
  33. data/.rubocop.yml +7 -39
  34. data/.yard-lint.yml +75 -0
  35. data/CONTRIBUTING.md +186 -174
  36. data/Gemfile +17 -0
  37. data/README.md +47 -12
  38. data/Rakefile +3 -21
  39. data/UPGRADING.md +219 -70
  40. data/docker/test/Dockerfile +32 -0
  41. data/docker/test/docker-compose.yml +0 -0
  42. data/git.gemspec +3 -4
  43. data/lib/git/author.rb +20 -1
  44. data/lib/git/branch.rb +26 -6
  45. data/lib/git/branch_delete_failure.rb +3 -0
  46. data/lib/git/branch_delete_result.rb +6 -3
  47. data/lib/git/branch_info.rb +6 -6
  48. data/lib/git/command_line/base.rb +6 -13
  49. data/lib/git/command_line/capturing.rb +67 -10
  50. data/lib/git/command_line/result.rb +0 -8
  51. data/lib/git/command_line/streaming.rb +45 -5
  52. data/lib/git/command_line.rb +4 -3
  53. data/lib/git/commands/add.rb +61 -53
  54. data/lib/git/commands/am/abort.rb +2 -2
  55. data/lib/git/commands/am/apply.rb +109 -98
  56. data/lib/git/commands/am/continue.rb +2 -2
  57. data/lib/git/commands/am/quit.rb +2 -2
  58. data/lib/git/commands/am/retry.rb +4 -2
  59. data/lib/git/commands/am/show_current_patch.rb +1 -1
  60. data/lib/git/commands/am/skip.rb +2 -2
  61. data/lib/git/commands/am.rb +2 -2
  62. data/lib/git/commands/apply.rb +7 -2
  63. data/lib/git/commands/archive/list_formats.rb +3 -3
  64. data/lib/git/commands/archive.rb +7 -2
  65. data/lib/git/commands/arguments.rb +1370 -359
  66. data/lib/git/commands/base.rb +111 -13
  67. data/lib/git/commands/branch/copy.rb +29 -21
  68. data/lib/git/commands/branch/create.rb +72 -68
  69. data/lib/git/commands/branch/delete.rb +25 -17
  70. data/lib/git/commands/branch/list.rb +76 -60
  71. data/lib/git/commands/branch/move.rb +29 -21
  72. data/lib/git/commands/branch/set_upstream.rb +8 -8
  73. data/lib/git/commands/branch/show_current.rb +3 -3
  74. data/lib/git/commands/branch/unset_upstream.rb +4 -8
  75. data/lib/git/commands/branch.rb +2 -2
  76. data/lib/git/commands/cat_file/batch.rb +36 -20
  77. data/lib/git/commands/cat_file/filtered.rb +12 -12
  78. data/lib/git/commands/cat_file/raw.rb +13 -13
  79. data/lib/git/commands/cat_file.rb +4 -4
  80. data/lib/git/commands/checkout/branch.rb +7 -5
  81. data/lib/git/commands/checkout/files.rb +5 -4
  82. data/lib/git/commands/checkout.rb +4 -4
  83. data/lib/git/commands/checkout_index.rb +5 -4
  84. data/lib/git/commands/clean.rb +6 -4
  85. data/lib/git/commands/clone.rb +5 -4
  86. data/lib/git/commands/commit.rb +5 -4
  87. data/lib/git/commands/commit_tree.rb +5 -4
  88. data/lib/git/commands/config_option_syntax/add.rb +7 -4
  89. data/lib/git/commands/config_option_syntax/get.rb +9 -5
  90. data/lib/git/commands/config_option_syntax/get_all.rb +7 -4
  91. data/lib/git/commands/config_option_syntax/get_color.rb +8 -4
  92. data/lib/git/commands/config_option_syntax/get_color_bool.rb +7 -4
  93. data/lib/git/commands/config_option_syntax/get_regexp.rb +8 -4
  94. data/lib/git/commands/config_option_syntax/get_urlmatch.rb +8 -4
  95. data/lib/git/commands/config_option_syntax/list.rb +8 -4
  96. data/lib/git/commands/config_option_syntax/remove_section.rb +7 -2
  97. data/lib/git/commands/config_option_syntax/rename_section.rb +7 -2
  98. data/lib/git/commands/config_option_syntax/replace_all.rb +7 -2
  99. data/lib/git/commands/config_option_syntax/set.rb +7 -2
  100. data/lib/git/commands/config_option_syntax/unset.rb +7 -4
  101. data/lib/git/commands/config_option_syntax/unset_all.rb +7 -2
  102. data/lib/git/commands/describe.rb +5 -4
  103. data/lib/git/commands/diff.rb +13 -12
  104. data/lib/git/commands/diff_files.rb +7 -6
  105. data/lib/git/commands/diff_index.rb +10 -7
  106. data/lib/git/commands/fetch.rb +6 -4
  107. data/lib/git/commands/fsck.rb +6 -4
  108. data/lib/git/commands/gc.rb +6 -4
  109. data/lib/git/commands/grep.rb +6 -5
  110. data/lib/git/commands/init.rb +6 -4
  111. data/lib/git/commands/log.rb +287 -285
  112. data/lib/git/commands/ls_files.rb +69 -65
  113. data/lib/git/commands/ls_remote.rb +62 -56
  114. data/lib/git/commands/ls_tree.rb +50 -46
  115. data/lib/git/commands/maintenance/register.rb +25 -23
  116. data/lib/git/commands/maintenance/run.rb +7 -2
  117. data/lib/git/commands/maintenance/start.rb +7 -2
  118. data/lib/git/commands/maintenance/stop.rb +7 -2
  119. data/lib/git/commands/maintenance/unregister.rb +7 -2
  120. data/lib/git/commands/merge/abort.rb +2 -2
  121. data/lib/git/commands/merge/continue.rb +2 -2
  122. data/lib/git/commands/merge/quit.rb +2 -2
  123. data/lib/git/commands/merge/start.rb +7 -2
  124. data/lib/git/commands/merge.rb +2 -2
  125. data/lib/git/commands/merge_base.rb +7 -2
  126. data/lib/git/commands/mv.rb +7 -2
  127. data/lib/git/commands/name_rev.rb +7 -2
  128. data/lib/git/commands/pull.rb +7 -2
  129. data/lib/git/commands/push.rb +7 -2
  130. data/lib/git/commands/read_tree.rb +7 -2
  131. data/lib/git/commands/remote/add.rb +7 -2
  132. data/lib/git/commands/remote/get_url.rb +4 -2
  133. data/lib/git/commands/remote/list.rb +4 -2
  134. data/lib/git/commands/remote/prune.rb +4 -2
  135. data/lib/git/commands/remote/remove.rb +4 -2
  136. data/lib/git/commands/remote/rename.rb +4 -2
  137. data/lib/git/commands/remote/set_branches.rb +9 -2
  138. data/lib/git/commands/remote/set_head.rb +12 -5
  139. data/lib/git/commands/remote/set_url.rb +9 -2
  140. data/lib/git/commands/remote/set_url_add.rb +11 -2
  141. data/lib/git/commands/remote/set_url_delete.rb +9 -2
  142. data/lib/git/commands/remote/show.rb +18 -12
  143. data/lib/git/commands/remote/update.rb +19 -12
  144. data/lib/git/commands/remote.rb +2 -2
  145. data/lib/git/commands/repack.rb +67 -63
  146. data/lib/git/commands/reset.rb +51 -44
  147. data/lib/git/commands/rev_parse.rb +135 -128
  148. data/lib/git/commands/revert/abort.rb +2 -2
  149. data/lib/git/commands/revert/continue.rb +7 -2
  150. data/lib/git/commands/revert/quit.rb +2 -2
  151. data/lib/git/commands/revert/skip.rb +2 -2
  152. data/lib/git/commands/revert/start.rb +7 -2
  153. data/lib/git/commands/revert.rb +2 -2
  154. data/lib/git/commands/rm.rb +35 -36
  155. data/lib/git/commands/show.rb +1 -1
  156. data/lib/git/commands/show_ref/exclude_existing.rb +3 -4
  157. data/lib/git/commands/show_ref/exists.rb +15 -13
  158. data/lib/git/commands/show_ref/list.rb +39 -35
  159. data/lib/git/commands/show_ref/verify.rb +29 -27
  160. data/lib/git/commands/show_ref.rb +4 -4
  161. data/lib/git/commands/stash/apply.rb +31 -25
  162. data/lib/git/commands/stash/branch.rb +10 -8
  163. data/lib/git/commands/stash/clear.rb +7 -5
  164. data/lib/git/commands/stash/create.rb +10 -8
  165. data/lib/git/commands/stash/drop.rb +15 -9
  166. data/lib/git/commands/stash/list.rb +9 -5
  167. data/lib/git/commands/stash/pop.rb +21 -12
  168. data/lib/git/commands/stash/push.rb +20 -11
  169. data/lib/git/commands/stash/show.rb +21 -12
  170. data/lib/git/commands/stash/store.rb +19 -10
  171. data/lib/git/commands/stash.rb +2 -2
  172. data/lib/git/commands/status.rb +7 -2
  173. data/lib/git/commands/symbolic_ref/delete.rb +18 -14
  174. data/lib/git/commands/symbolic_ref/read.rb +24 -20
  175. data/lib/git/commands/symbolic_ref/update.rb +20 -17
  176. data/lib/git/commands/symbolic_ref.rb +4 -4
  177. data/lib/git/commands/tag/create.rb +45 -42
  178. data/lib/git/commands/tag/delete.rb +5 -3
  179. data/lib/git/commands/tag/list.rb +47 -44
  180. data/lib/git/commands/tag/verify.rb +12 -12
  181. data/lib/git/commands/tag.rb +2 -2
  182. data/lib/git/commands/update_ref/batch.rb +6 -1
  183. data/lib/git/commands/update_ref/delete.rb +19 -21
  184. data/lib/git/commands/update_ref/update.rb +22 -25
  185. data/lib/git/commands/update_ref.rb +4 -4
  186. data/lib/git/commands/version.rb +14 -11
  187. data/lib/git/commands/worktree/add.rb +50 -51
  188. data/lib/git/commands/worktree/list.rb +17 -17
  189. data/lib/git/commands/worktree/lock.rb +12 -12
  190. data/lib/git/commands/worktree/move.rb +16 -16
  191. data/lib/git/commands/worktree/prune.rb +2 -2
  192. data/lib/git/commands/worktree/remove.rb +2 -2
  193. data/lib/git/commands/worktree/repair.rb +2 -2
  194. data/lib/git/commands/worktree/unlock.rb +2 -2
  195. data/lib/git/commands/write_tree.rb +2 -2
  196. data/lib/git/commands.rb +4 -3
  197. data/lib/git/config.rb +47 -1
  198. data/lib/git/configuring.rb +89 -15
  199. data/lib/git/detached_head_info.rb +4 -1
  200. data/lib/git/diff.rb +2 -5
  201. data/lib/git/diff_file_numstat_info.rb +3 -1
  202. data/lib/git/diff_file_patch_info.rb +3 -1
  203. data/lib/git/diff_file_raw_info.rb +3 -1
  204. data/lib/git/diff_info.rb +8 -15
  205. data/lib/git/diff_path_status.rb +16 -3
  206. data/lib/git/diff_result.rb +3 -1
  207. data/lib/git/diff_stats.rb +15 -0
  208. data/lib/git/dirstat_info.rb +24 -8
  209. data/lib/git/encoding_utils.rb +32 -1
  210. data/lib/git/errors.rb +19 -9
  211. data/lib/git/escaped_path.rb +55 -3
  212. data/lib/git/execution_context/repository.rb +15 -0
  213. data/lib/git/execution_context.rb +76 -74
  214. data/lib/git/file_ref.rb +6 -3
  215. data/lib/git/fsck_object.rb +8 -0
  216. data/lib/git/fsck_result.rb +26 -15
  217. data/lib/git/log.rb +152 -5
  218. data/lib/git/object.rb +284 -8
  219. data/lib/git/parsers/branch.rb +18 -0
  220. data/lib/git/parsers/cat_file.rb +2 -2
  221. data/lib/git/parsers/diff.rb +213 -5
  222. data/lib/git/parsers/fsck.rb +11 -0
  223. data/lib/git/parsers/ls_remote.rb +1 -1
  224. data/lib/git/parsers/stash.rb +51 -0
  225. data/lib/git/parsers/tag.rb +38 -0
  226. data/lib/git/remote.rb +34 -2
  227. data/lib/git/repository/branching.rb +23 -21
  228. data/lib/git/repository/committing.rb +46 -6
  229. data/lib/git/repository/context_helpers.rb +45 -16
  230. data/lib/git/repository/diffing.rb +32 -23
  231. data/lib/git/repository/factories.rb +153 -28
  232. data/lib/git/repository/inspecting.rb +1 -1
  233. data/lib/git/repository/logging.rb +169 -30
  234. data/lib/git/repository/maintenance.rb +1 -1
  235. data/lib/git/repository/merging.rb +3 -3
  236. data/lib/git/repository/object_operations.rb +108 -14
  237. data/lib/git/repository/remote_operations.rb +150 -171
  238. data/lib/git/repository/shared_private.rb +7 -5
  239. data/lib/git/repository/staging.rb +36 -12
  240. data/lib/git/repository/stashing.rb +16 -16
  241. data/lib/git/repository/status_operations.rb +1 -1
  242. data/lib/git/repository/worktree_operations.rb +1 -1
  243. data/lib/git/repository.rb +123 -63
  244. data/lib/git/stash.rb +16 -21
  245. data/lib/git/stash_info.rb +4 -4
  246. data/lib/git/stashes.rb +20 -26
  247. data/lib/git/status.rb +21 -7
  248. data/lib/git/tag_delete_failure.rb +3 -0
  249. data/lib/git/tag_delete_result.rb +6 -3
  250. data/lib/git/tag_info.rb +1 -0
  251. data/lib/git/url.rb +12 -5
  252. data/lib/git/version.rb +6 -4
  253. data/lib/git/version_constraint.rb +4 -0
  254. data/lib/git.rb +398 -314
  255. data/redesign/3_architecture_implementation.md +59 -29
  256. data/redesign/Phase 4 - Step B.md +921 -0
  257. data/redesign/Phase 4 - Step C.md +833 -0
  258. data/redesign/c1a-public-api-scope.tsv +256 -0
  259. data/redesign/phase-4-step-b-test-audit.tsv +485 -0
  260. data/tasks/yard.rake +24 -17
  261. metadata +24 -57
  262. data/commitlint.test +0 -4
  263. data/lib/git/args_builder.rb +0 -103
  264. data/lib/git/command_line_result.rb +0 -8
  265. data/lib/git/deprecation.rb +0 -9
  266. data/tasks/test.rake +0 -25
  267. /data/.github/{skills → skills-deprecated}/extract-facade-from-base-lib/KEYWORD_ARG_REMEDIATION.md +0 -0
  268. /data/.github/{skills → skills-deprecated}/review-backward-compatibility/SKILL.md +0 -0
@@ -12,15 +12,51 @@ General YARD documentation rules and workflow for all Ruby source code.
12
12
  - [Contents](#contents)
13
13
  - [How to use this skill](#how-to-use-this-skill)
14
14
  - [Related skills](#related-skills)
15
- - [Documentation Standards](#documentation-standards)
16
- - [YARD Formatting Rules](#yard-formatting-rules)
17
- - [Element-Specific Rules](#element-specific-rules)
15
+ - [Reference files](#reference-files)
16
+ - [Precedence](#precedence)
17
+ - [Workflow](#workflow)
18
+ - [Named length limits](#named-length-limits)
18
19
  - [Step 1: Identify What Needs Documentation](#step-1-identify-what-needs-documentation)
19
20
  - [Step 2: Write Documentation](#step-2-write-documentation)
20
21
  - [Standard template (no `@overload`)](#standard-template-no-overload)
21
22
  - [Overload template](#overload-template)
23
+ - [Overload decision matrix](#overload-decision-matrix)
22
24
  - [Documenting anonymous splats with `@overload`](#documenting-anonymous-splats-with-overload)
25
+ - [Documenting other elements](#documenting-other-elements)
23
26
  - [Step 3: Verify Documentation](#step-3-verify-documentation)
27
+ - [Line and summary length checks](#line-and-summary-length-checks)
28
+ - [Documentation Standards](#documentation-standards)
29
+ - [Formatting Rules](#formatting-rules)
30
+ - [Doc comment placement](#doc-comment-placement)
31
+ - [Blank lines around tags](#blank-lines-around-tags)
32
+ - [Never use raw blank lines inside a doc comment block](#never-use-raw-blank-lines-inside-a-doc-comment-block)
33
+ - [Short descriptions](#short-descriptions)
34
+ - [Line and summary length](#line-and-summary-length)
35
+ - [`@return` must always include a type](#return-must-always-include-a-type)
36
+ - [No shell calls in `@example` blocks](#no-shell-calls-in-example-blocks)
37
+ - [Blank lines within `@example` blocks](#blank-lines-within-example-blocks)
38
+ - [`@example` titles are required](#example-titles-are-required)
39
+ - [Cross-reference links only resolve to objects included in generated docs](#cross-reference-links-only-resolve-to-objects-included-in-generated-docs)
40
+ - [Inline code formatting](#inline-code-formatting)
41
+ - [Escaping opening braces in descriptions](#escaping-opening-braces-in-descriptions)
42
+ - [Cross-reference links](#cross-reference-links)
43
+ - [Type specifier conventions](#type-specifier-conventions)
44
+ - [`Array<...>` (collection) vs `Array(...)` (tuple)](#array-collection-vs-array-tuple)
45
+ - [`@api private` vs `@private`](#api-private-vs-private)
46
+ - [Class and module `@api` visibility (Required)](#class-and-module-api-visibility-required)
47
+ - [`@since` tags are not used](#since-tags-are-not-used)
48
+ - [`@todo` tags are not used](#todo-tags-are-not-used)
49
+ - [`@abstract`](#abstract)
50
+ - [Method Rules](#method-rules)
51
+ - [Short description](#short-description)
52
+ - [Standard tags](#standard-tags)
53
+ - [`@example` on non-private methods](#example-on-non-private-methods)
54
+ - [Yield tags](#yield-tags)
55
+ - [`@overload` for distinct signatures](#overload-for-distinct-signatures)
56
+ - [`@overload` for anonymous splats](#overload-for-anonymous-splats)
57
+ - [`@note` for callouts (Optional)](#note-for-callouts-optional)
58
+ - [`@deprecated` on deprecated methods](#deprecated-on-deprecated-methods)
59
+ - [`@api` on methods (Optional)](#api-on-methods-optional)
24
60
  - [Command Reference](#command-reference)
25
61
 
26
62
  ## How to use this skill
@@ -29,63 +65,524 @@ Attach this file to your Copilot Chat context, then invoke it with the source
29
65
  files that need YARD updates. Use it when adding new APIs, fixing doc warnings,
30
66
  or improving existing YARD quality and examples.
31
67
 
32
- ## Related skills
68
+ Work top to bottom: follow the three-step [Workflow](#workflow), reaching into the
69
+ [Documentation Standards](#documentation-standards) reference below as you write,
70
+ and into [`element-rules.md`](element-rules.md) when documenting a class, module,
71
+ constant, attribute, dynamically defined method, or value object.
72
+
73
+ ## Related skills
74
+
75
+ - [Command YARD Documentation](../command-yard-documentation/SKILL.md) — command-specific rules for writing and reviewing YARD docs on `Git::Commands::Base` subclasses
76
+
77
+ ## Reference files
78
+
79
+ Situational rules live in a sibling file, loaded only when the element type calls
80
+ for it:
81
+
82
+ - [`element-rules.md`](element-rules.md) — per-element requirements for **classes,
83
+ modules, constants, attributes, dynamically defined methods**, and value
84
+ objects (`Data.define` / `Struct.new`). Read it whenever you document one
85
+ of those elements. Rules for **methods** and rules that apply to **every** doc
86
+ comment stay in this file.
87
+
88
+ ## Precedence
89
+
90
+ When a more specific YARD skill applies, its rules override this general skill:
91
+
92
+ - [Command YARD Documentation](../command-yard-documentation/SKILL.md) overrides
93
+ these rules for `Git::Commands::Base` subclasses.
94
+ - [Facade YARD Documentation](../facade-yard-documentation/SKILL.md) overrides these
95
+ rules for `Git::Repository::*` topic modules.
96
+
97
+ Otherwise, the rules in this file apply to all Ruby source.
98
+
99
+ ## Workflow
100
+
101
+ Documenting or fixing YARD docs follows three steps:
102
+
103
+ 1. [Step 1: Identify What Needs Documentation](#step-1-identify-what-needs-documentation)
104
+ 2. [Step 2: Write Documentation](#step-2-write-documentation) — apply the
105
+ templates and the [Documentation Standards](#documentation-standards)
106
+ 3. [Step 3: Verify Documentation](#step-3-verify-documentation) — lint, build,
107
+ and manually check
108
+
109
+ ruby-git uses YARD for API documentation. All classes, modules, constants,
110
+ attributes, and methods must have YARD documentation. Methods with Ruby `private`
111
+ visibility require a short description and all applicable tags from the
112
+ [Method Rules](#method-rules) — `@param`, `@return`, `@raise`,
113
+ `@yield`/`@yieldparam`/`@yieldreturn`, and `@overload` — with the exception that
114
+ `@example` may be omitted unless an example materially clarifies the behavior.
115
+ Private methods still need YARD docs for developer reference in source, even though
116
+ YARD excludes them from generated HTML by default.
117
+
118
+ ## Named length limits
119
+
120
+ Three named limits govern line and description length throughout this skill. They
121
+ are referenced by name in [Step 3](#step-3-verify-documentation) and the
122
+ [Formatting Rules](#formatting-rules):
123
+
124
+ - **`LINE_LIMIT`** (90 characters) — the preferred maximum length of any
125
+ physical YARD comment line, measured from column 1 and including every
126
+ character: indentation, `#`, tag metadata, and all text. Wrap prose at
127
+ this limit wherever possible.
128
+ - **`LINE_MAX`** (120 characters) — the hard ceiling for lines that cannot
129
+ be wrapped without breaking their meaning. The following content may
130
+ exceed `LINE_LIMIT` up to `LINE_MAX`; it must not exceed `LINE_MAX`:
131
+ - **URLs** — in `@see` tags or markdown links; a URL cannot be split
132
+ - **Long inline code spans** — a `` `backtick` `` span whose content
133
+ alone approaches or exceeds `LINE_LIMIT`
134
+ - **Long `[Type]` expressions** — a type such as
135
+ `[String, Pathname, Array<String, Pathname>]` that fills the tag
136
+ metadata column before any description text begins
137
+ - **`@example` code lines** — real code inside an example block that
138
+ cannot be reflowed without changing its meaning
139
+ - **Markdown table rows** — pipe-delimited table rows that cannot be
140
+ split across lines
141
+ - **`SUMMARY_LIMIT`** (90 characters) — the maximum length of a short
142
+ description — either a tag's description text or a documentable object's short
143
+ description (class, module, method, constant, or attribute) — measured by
144
+ concatenating the text from the first line with all immediately following
145
+ indented continuation lines (stripping the leading `#` and continuation indent
146
+ from each and joining with a single space).
147
+ For tags, this covers the description text only — not the tag name, `[Type]`,
148
+ option key, or `(default)`.
149
+
150
+ ## Step 1: Identify What Needs Documentation
151
+
152
+ ```bash
153
+ # Find undocumented objects
154
+ bundle exec yard stats --list-undoc
155
+
156
+ # Check a specific file
157
+ bundle exec yard doc lib/git/repository.rb --no-output
158
+ ```
159
+
160
+ ## Step 2: Write Documentation
161
+
162
+ Follow the YARD documentation templates below and apply the
163
+ [Documentation Standards](#documentation-standards) as you write. Use the
164
+ **standard template** when a method has a single call signature. Use the
165
+ **overload template** when a method has distinct call signatures with different
166
+ parameters or return types.
167
+
168
+ When `@overload` blocks are present:
169
+
170
+ - Keep signature-specific tags inside overload blocks only:
171
+ `@example`, `@param`, `@option`, `@return`, overload-specific `@raise`,
172
+ and `@yield`/`@yieldparam`/`@yieldreturn`
173
+ - Keep `@return` inside each `@overload` block. For overloaded methods,
174
+ `@return` is overload-scoped even when the return type/text is the same
175
+ across call shapes
176
+ - Keep shared `@raise` at top level only once (outside all overload blocks)
177
+ - Keep `@raise` inside an overload only when that exception applies to that
178
+ overload shape only
179
+ - Never document the same `@raise` in both places (top-level and overload)
180
+ - Keep non-signature tags (`@note`, `@deprecated`, `@see`, `@api`) at top level
181
+ - Never nest `@api` inside an `@overload` block; it applies to the method
182
+ itself, not to an individual call shape
183
+
184
+ Correct placement pattern:
185
+
186
+ ```ruby
187
+ # @overload fetch(name)
188
+ #
189
+ # @param name [String] the remote name
190
+ #
191
+ # @return [Git::CommandLineResult] the command result
192
+ #
193
+ # @overload fetch(name, **options)
194
+ #
195
+ # @param name [String] the remote name
196
+ #
197
+ # @param options [Hash] command options
198
+ #
199
+ # @return [Git::CommandLineResult] the command result
200
+ #
201
+ # @raise [ArgumentError] when the remote name is invalid
202
+ #
203
+ # @api public
204
+ ```
205
+
206
+ Incorrect placement pattern:
207
+
208
+ ```ruby
209
+ # @overload fetch(name)
210
+ #
211
+ # @param name [String] the remote name
212
+ #
213
+ # @return [Git::CommandLineResult] the command result
214
+ #
215
+ # @raise [ArgumentError] when the remote name is invalid
216
+ #
217
+ # @overload fetch(name, **options)
218
+ #
219
+ # @param name [String] the remote name
220
+ #
221
+ # @param options [Hash] command options
222
+ #
223
+ # @raise [ArgumentError] when the remote name is invalid
224
+ #
225
+ # @api public
226
+ ```
227
+
228
+ **Trigger: always use `@overload` for anonymous `*`, anonymous `**`, or `...`**
229
+
230
+ Anonymous splats and the forwarding parameter give `@param`, `@option`, `@yield`,
231
+ and `@yieldparam` no named parameter to bind to, so YARD silently drops them.
232
+ Switch to `@overload` for the entire signature — see
233
+ [Documenting anonymous splats with `@overload`](#documenting-anonymous-splats-with-overload).
234
+
235
+ ### Standard template (no `@overload`)
236
+
237
+ When present, tags must appear in the order shown. `@param` tags appear in
238
+ parameter order, with one exception described below; `@option` tags appear
239
+ immediately after the `@param` for the hash they describe. Every `@option` tag
240
+ **must** be preceded by a `@param` for the options hash, and all `@option` tags
241
+ under that `@param` must reference the same parameter name. For keyword arguments
242
+ (`**options` or `**kwargs`), use `@param options [Hash]` (or the actual splat
243
+ name) as the preceding `@param`.
244
+
245
+ For public APIs with known option keys, every `@option` tag must document a real
246
+ supported key, such as `:force` or `:timeout`. Do not invent placeholder option
247
+ keys for a public `options` hash.
248
+
249
+ For private helpers that accept arbitrary keyword collectors whose keys are
250
+ validated elsewhere, use a neutral splat name such as `candidate_keywords` and
251
+ document the collector shape with a single pseudo-option entry named `key_name`.
252
+ A pseudo-option is required because yard-lint's `Documentation/UndocumentedOptions`
253
+ flags any documented `**` collector that has no `@option` tag, and that check has
254
+ no type, name, or visibility exemption for double-splats. Use `key_name` rather
255
+ than a literal-looking `key` so it is not mistaken for a real option key. This is
256
+ only for arbitrary-keyword helpers where the accepted keys are intentionally not
257
+ known at that abstraction layer:
258
+
259
+ ```ruby
260
+ # Validate that candidate option keys are listed in `allowed`
261
+ #
262
+ # @param allowed [Array<Symbol>] the permitted option keys
263
+ #
264
+ # @param candidate_keywords [Hash<Symbol, Object>] the keywords to validate
265
+ #
266
+ # @option candidate_keywords [Object] key_name a candidate keyword value
267
+ #
268
+ # @return [void]
269
+ #
270
+ # @raise [ArgumentError] when any candidate key is not in `allowed`
271
+ #
272
+ def assert_valid_opts!(allowed, **candidate_keywords)
273
+ end
274
+ ```
275
+
276
+ The exception to parameter order: all `@param` tags must come before the first
277
+ `@option` tag, because yard-lint's `Tags/Order` validator rejects a `@param` that
278
+ follows an `@option`. When a positional parameter follows the options hash in the
279
+ signature, document the options-hash `@param` (and its `@option` tags) last so the
280
+ `@option` tags stay grouped at the end — that is, move the options-hash `@param`
281
+ after the later positional `@param` rather than in strict signature order:
282
+
283
+ ```ruby
284
+ # Short description of what the method does
285
+ #
286
+ # Longer description with more details about behavior,
287
+ # edge cases, or important notes.
288
+ #
289
+ # @example Basic usage
290
+ # git = Git.open('/path/to/repo')
291
+ # result = git.method_name('arg', {}, '/path')
292
+ #
293
+ # @example With options
294
+ # git.method_name('arg', { option: true }, '/path')
295
+ #
296
+ # @param name [Type] description of parameter
297
+ #
298
+ # @param path [String] a parameter that follows the options hash in the signature
299
+ #
300
+ # @param options [Hash] options hash description
301
+ #
302
+ # @option options [Type] :key description of option
303
+ #
304
+ # @return [Type] description of return value
305
+ #
306
+ # @raise [ArgumentError] when invalid arguments are provided
307
+ #
308
+ # @raise [Git::FailedError] when git exits with a non-zero exit status
309
+ #
310
+ # @yield [commit] passes each commit to the block
311
+ #
312
+ # @yieldparam commit [Git::Object::Commit] a commit object
313
+ #
314
+ # @yieldreturn [void]
315
+ #
316
+ # @note This method is not thread-safe
317
+ #
318
+ # @deprecated Use {#new_method} instead
319
+ #
320
+ # @see #related_method
321
+ #
322
+ # @see Git::RelatedClass
323
+ #
324
+ # @see https://git-scm.com/docs/git-log
325
+ #
326
+ # @api public
327
+ #
328
+ def method_name(name, options = {}, path)
329
+ end
330
+ ```
331
+
332
+ ### Overload template
333
+
334
+ Each `@overload` block carries only signature-specific tags: `@example`,
335
+ `@param`, `@option`, `@return`, overload-specific `@raise`, and
336
+ `@yield`/`@yieldparam`/`@yieldreturn`. Tags that are **not**
337
+ call-signature-specific — `@note`, `@deprecated`, `@see`, `@api` — remain
338
+ at the top level. `@return` remains overload-scoped even when identical across
339
+ call shapes. `@raise` can be top-level when shared across all call shapes, and
340
+ overload-local when shape-specific. Never place `@api` inside an overload
341
+ block.
342
+
343
+ ```ruby
344
+ # Short description of what the method does
345
+ #
346
+ # Longer description with more details about behavior,
347
+ # edge cases, or important notes.
348
+ #
349
+ # @overload method_name(arg)
350
+ #
351
+ # Single-argument form description
352
+ #
353
+ # @example Basic usage
354
+ # result = git.method_name('arg')
355
+ #
356
+ # @param arg [String] the argument
357
+ #
358
+ # @return [String] the result
359
+ #
360
+ # @overload method_name(arg, options)
361
+ #
362
+ # Two-argument form description
363
+ #
364
+ # @example With options
365
+ # result = git.method_name('arg', { force: true })
366
+ #
367
+ # @param arg [String] the argument
368
+ #
369
+ # @param options [Hash] additional options
370
+ #
371
+ # @return [Array<String>] the results
372
+ #
373
+ # @raise [ArgumentError] when an invalid argument is provided
374
+ #
375
+ # @note This method is not thread-safe
376
+ #
377
+ # @deprecated Use {#new_method} instead
378
+ #
379
+ # @see #related_method
380
+ #
381
+ # @see https://git-scm.com/docs/git-log
382
+ #
383
+ # @api public
384
+ #
385
+ def method_name(arg, options = {})
386
+ end
387
+ ```
388
+
389
+ ### Overload decision matrix
390
+
391
+ Use this matrix to decide whether to use `@overload` and where to place tags:
392
+
393
+ | Method signature or behavior | Documentation form |
394
+ | --- | --- |
395
+ | Single named signature, no `*`/`**`/`...` | Standard template (no `@overload`) |
396
+ | Uses anonymous `*`, `**`, or `...` | `@overload` required |
397
+ | Private arbitrary keyword collector | Neutral splat name plus pseudo-option `key_name` |
398
+ | Multiple call shapes (different params and/or return types) | One `@overload` per shape |
399
+ | Return value for overloaded methods | `@return` in each overload; never top-level |
400
+ | Shared errors across all call shapes | Top-level `@raise` once (outside overloads) |
401
+ | Error only for specific call shape | `@raise` only in that overload |
402
+ | Same error documented top-level and inside overloads | Invalid; choose one placement |
403
+ | Method-level API visibility (`@api`) | Top-level `@api` only; never inside `@overload` |
404
+
405
+ ### Documenting anonymous splats with `@overload`
406
+
407
+ When the method signature uses an anonymous splat — `def foo(*)`, `def foo(**)`,
408
+ `def foo(*, **)` — or the argument forwarding parameter `def foo(...)` —
409
+ `@param`, `@option`, `@yield`, and `@yieldparam` tags have no parameter name
410
+ to bind to. RuboCop's `Style/ArgumentsForwarding` cop prefers these forms when
411
+ arguments are forwarded unchanged, so naming the splat (or expanding `...`
412
+ into `*args, **kwargs, &block`) is **not** an acceptable workaround. Use
413
+ `@overload` blocks that introduce named parameters for documentation purposes
414
+ only:
415
+
416
+ ```ruby
417
+ # Update the index with the current content found in the working tree
418
+ #
419
+ # @overload add(paths = '.', **options)
420
+ #
421
+ # @example Stage a specific file
422
+ # git.add('README.md')
423
+ #
424
+ # @param paths [String, Array<String>] file(s) to add (relative to the
425
+ # worktree root); defaults to `'.'` (all files)
426
+ #
427
+ # @param options [Hash] command options
428
+ #
429
+ # @option options [Boolean, nil] :all (nil) add, modify, and remove index entries to
430
+ # match the worktree
431
+ #
432
+ # @option options [Boolean, nil] :force (nil) allow adding otherwise ignored files
433
+ #
434
+ # @return [String] the command output
435
+ #
436
+ # @raise [Git::FailedError] if `git add` exits with a non-zero status
437
+ #
438
+ def add(paths = '.', **)
439
+ Git::Commands::Add.new(@execution_context).call(*Array(paths), **).stdout
440
+ end
441
+ ```
442
+
443
+ The same approach applies to `...`. The overload signature names the
444
+ parameters; the actual `def` keeps `...` so RuboCop is satisfied:
445
+
446
+ ```ruby
447
+ # Run a command against the underlying execution context
448
+ #
449
+ # @overload run(command, *args, **options, &block)
450
+ #
451
+ # @example Run git status
452
+ # result = git.run('status')
453
+ #
454
+ # @param command [String] the git subcommand to run
455
+ #
456
+ # @param args [Array<String>] positional arguments forwarded to the command
457
+ #
458
+ # @param options [Hash] keyword options forwarded to the command
459
+ #
460
+ # @return [Git::CommandLineResult] the command result
461
+ #
462
+ # @yield [result] yields the command result, when a block is given
463
+ #
464
+ # @yieldparam result [Git::CommandLineResult] the command result
465
+ #
466
+ # @yieldreturn [void]
467
+ #
468
+ def run(command, ...)
469
+ Git::Commands::Run.new(@execution_context).call(command, ...)
470
+ end
471
+ ```
472
+
473
+ When a method has multiple genuinely distinct call shapes, write one
474
+ `@overload` block per shape as in the [Overload template](#overload-template)
475
+ above.
476
+
477
+ **Anonymous block parameter (`&`)** is **not** covered by this rule.
478
+ `@yield`, `@yieldparam`, and `@yieldreturn` describe what is yielded to the
479
+ block, not the block parameter itself, so they bind correctly even with an
480
+ anonymous `&`. Use a named block parameter (`&block`) and a `@param block
481
+ [Proc]` tag only in the rare case where the block is documented as a
482
+ first-class `Proc` value (stored, returned, or passed elsewhere) rather than
483
+ yielded to.
484
+
485
+ ### Documenting other elements
486
+
487
+ The templates above cover **methods**. When documenting a **class, module,
488
+ constant, attribute, dynamically defined method (`@!method`)**, or a value
489
+ object (`Data.define` / `Struct.new`), follow the per-element requirements
490
+ in [`element-rules.md`](element-rules.md).
491
+
492
+ ## Step 3: Verify Documentation
493
+
494
+ First, run the automated linter. `yard-lint` enforces many of the rules in this
495
+ skill (undocumented objects, missing `@param`/`@option`/`@return`, tag order,
496
+ type syntax, orphaned doc comments) and the minimum documentation coverage
497
+ threshold:
498
+
499
+ ```bash
500
+ # Lint YARD docs against the project standards (config: .yard-lint.yml)
501
+ bundle exec yard-lint lib/
502
+
503
+ # Lint only the files you changed
504
+ bundle exec yard-lint lib/ --diff main
505
+
506
+ # Or run it through rake (build + lint + example-test)
507
+ bundle exec rake yard
508
+ ```
509
+
510
+ A clean `yard-lint` run is necessary but not sufficient: the linter cannot check
511
+ every rule here (e.g. the `LINE_LIMIT`/`LINE_MAX` distinction, `SUMMARY_LIMIT`,
512
+ short-description capitalization and punctuation, noun-phrase class descriptions,
513
+ required `@example` titles, class/module-level `@api` visibility correctness).
514
+ Still perform the manual checks below.
515
+
516
+ Legacy offenses are baselined in `.yard-lint-todo.yml`; when you touch a file
517
+ listed there, remove it from every `Exclude:` list that names it (a file may be
518
+ baselined under more than one validator) and fix the offenses as part of your
519
+ change.
520
+
521
+ Then generate and review the rendered docs:
522
+
523
+ ```bash
524
+ # Generate and review docs
525
+ bundle exec yard doc
526
+ # then open doc/index.html in your browser
527
+
528
+ # Check for warnings
529
+ bundle exec yard doc 2>&1 | ruby -ne 'puts $_ if $_ =~ /warn/i'
530
+ ```
531
+
532
+ Verify `@example` code runs correctly in `bundle exec bin/console`.
533
+ Check that all `@see` references point to valid targets.
534
+
535
+ ### Line and summary length checks
33
536
 
34
- - [Command YARD Documentation](../command-yard-documentation/SKILL.md) command-specific rules for writing and reviewing YARD docs on `Git::Commands::Base` subclasses
537
+ Apply these checks to every YARD doc comment the description on a class,
538
+ module, method, constant, or attribute, and every tag within it (`@param`,
539
+ `@return`, `@raise`, `@option`, `@yield`, `@yieldparam`, `@yieldreturn`, etc.).
540
+ Check all three limits:
541
+
542
+ 1. **`LINE_LIMIT`**: Count every character from column 1 (indentation, `#`,
543
+ metadata, text) on each physical line. If any wrappable line exceeds
544
+ `LINE_LIMIT`, split at a word boundary onto a continuation line (indented
545
+ two extra spaces). Apply this check to every continuation line
546
+ independently.
547
+ 2. **`LINE_MAX`**: Confirm no physical line exceeds `LINE_MAX` — the hard
548
+ ceiling that nothing may cross. Only unwrappable content (URLs, long inline
549
+ code spans, long `[Type]` expressions, `@example` code, markdown table rows)
550
+ may sit between `LINE_LIMIT` and `LINE_MAX`; every other line must stay
551
+ within `LINE_LIMIT`.
552
+ 3. **`SUMMARY_LIMIT`**: For each short description — a tag's description or a
553
+ documented object's short description — strip the leading `#` and its
554
+ indentation from every continuation line and join with a single space. If the
555
+ concatenated text exceeds `SUMMARY_LIMIT`, shorten it and move the excess into
556
+ a paragraph after a blank `#` line.
35
557
 
36
558
  ## Documentation Standards
37
559
 
38
- ruby-git uses YARD for API documentation:
560
+ The rules below are the reference the [Workflow](#workflow) draws on. The
561
+ [Formatting Rules](#formatting-rules) apply to every doc comment regardless of
562
+ element type; the [Method Rules](#method-rules) govern method doc comments.
563
+ Per-element rules for classes, modules, constants, attributes, and value objects
564
+ are in [`element-rules.md`](element-rules.md).
39
565
 
40
- All classes, modules, constants, attributes, and methods must have YARD
41
- documentation. Methods with Ruby `private` visibility require a short description
42
- and all applicable tags from the [Methods](#methods) rules `@param`, `@return`,
43
- `@raise`, `@yield`/`@yieldparam`/`@yieldreturn`, and `@overload` — with the
44
- exception that `@example` may be omitted unless an example materially clarifies
45
- the behavior. Private methods still need YARD docs for developer reference in
46
- source, even though YARD excludes them from generated HTML by default.
566
+ Treat every rule in this section as mandatory unless its heading is marked
567
+ **(SHOULD)** or **(Optional)**. Headings that name a descriptive topic (e.g.
568
+ type-specifier conventions) are reference material; any obligations they carry are
569
+ stated with “must” inline.
47
570
 
48
- ### YARD Formatting Rules
571
+ ### Formatting Rules
49
572
 
50
573
  Doc comments are rendered as **markdown** via the redcarpet gem. Write all
51
574
  free-text descriptions, tag values, and examples using markdown syntax. These rules
52
- apply to all documentation regardless of element type:
53
-
54
- **Named length limits**
55
-
56
- Three named limits govern line and description length throughout this document:
57
-
58
- - **`LINE_LIMIT`** (90 characters) — the preferred maximum length of any
59
- physical YARD comment line, measured from column 1 and including every
60
- character: indentation, `#`, tag metadata, and all text. Wrap prose at
61
- this limit wherever possible.
62
- - **`LINE_MAX`** (120 characters) — the hard ceiling for lines that cannot
63
- be wrapped without breaking their meaning. The following content may
64
- exceed `LINE_LIMIT` up to `LINE_MAX`; it must not exceed `LINE_MAX`:
65
- - **URLs** — in `@see` tags or markdown links; a URL cannot be split
66
- - **Long inline code spans** — a `` `backtick` `` span whose content
67
- alone approaches or exceeds `LINE_LIMIT`
68
- - **Long `[Type]` expressions** — a type such as
69
- `[String, Pathname, Array<String, Pathname>]` that fills the tag
70
- metadata column before any description text begins
71
- - **`@example` code lines** — real code inside an example block that
72
- cannot be reflowed without changing its meaning
73
- - **Markdown table rows** — pipe-delimited table rows that cannot be
74
- split across lines
75
- - **`SUMMARY_LIMIT`** (90 characters) — the maximum length of a tag's
76
- description text, measured by concatenating the description from the first
77
- tag line with all immediately following indented continuation lines
78
- (stripping the leading `# ` from each and joining with a single space).
79
- Applies to the description text only — not the tag name, `[Type]`, option
80
- key, or `(default)`.
575
+ apply to all documentation regardless of element type. They reference the three
576
+ [Named length limits](#named-length-limits) (`LINE_LIMIT`, `LINE_MAX`,
577
+ `SUMMARY_LIMIT`) defined earlier.
81
578
 
82
- **Doc comment placement**
579
+ #### Doc comment placement
83
580
 
84
581
  YARD doc comments must appear immediately above the element they document (class,
85
582
  module, method, constant, or attribute) with no intervening blank lines or
86
583
  non-comment code.
87
584
 
88
- **Blank lines around tags**
585
+ #### Blank lines around tags
89
586
 
90
587
  Every individual YARD tag must be preceded by a blank comment line (`#`) unless it is the very first line of a doc comment.
91
588
  A YARD tag is any comment token matching `@!?[a-z_]+` — that is, `@word` (regular
@@ -95,7 +592,7 @@ etc.) or `@!word` (directives such as `@!attribute`, `@!method`, `@!scope`, etc.
95
592
  Within the tag block there are no other exceptions: consecutive same-kind tags (e.g.
96
593
  multiple `@param` lines) each require their own preceding blank line.
97
594
 
98
- **Never use raw blank lines inside a doc comment block**
595
+ #### Never use raw blank lines inside a doc comment block
99
596
 
100
597
  A raw blank line — an empty line with no leading `#` — terminates the YARD doc
101
598
  comment block at that point. Any comment lines that follow the raw blank line are
@@ -122,7 +619,7 @@ Incorrect — raw blank line silently drops the alias note:
122
619
  Watch for editors that auto-strip trailing spaces from `#` lines, silently
123
620
  creating raw blank lines.
124
621
 
125
- **Short descriptions**
622
+ #### Short descriptions
126
623
 
127
624
  The short description (the first sentence of any doc comment, or the inline text of
128
625
  a `@param`, `@return`, `@raise`, etc. tag) must:
@@ -140,23 +637,23 @@ a `@param`, `@return`, `@raise`, etc. tag) must:
140
637
  For tags, the **summary text** is the description that follows the tag
141
638
  metadata (tag name, `[Type]`, option key, and `(default)`). For example, in:
142
639
 
143
- ```
640
+ ```text
144
641
  @option options [Boolean, nil] :ignore_case (nil) ignore case distinctions
145
642
  ```
146
643
 
147
644
  the summary text is `ignore case distinctions`.
148
645
 
149
- **Tag line and summary length**
646
+ #### Line and summary length
150
647
 
151
- Every physical YARD doc line should not exceed `LINE_LIMIT`. When a tag's
152
- description would push a line past `LINE_LIMIT`, split it at a word boundary
648
+ Every physical YARD doc line should not exceed `LINE_LIMIT`. When a description
649
+ would push a line past `LINE_LIMIT`, split it at a word boundary
153
650
  onto a continuation line indented two extra spaces. For content that cannot
154
651
  be wrapped (URLs, long inline code spans, long `[Type]` expressions,
155
652
  `@example` code lines, markdown table rows), lines may extend up to
156
653
  `LINE_MAX` but must not exceed it.
157
654
 
158
655
  Additionally, the concatenated description — the description text from the
159
- first tag line joined with all continuation lines — must not exceed
656
+ first line joined with all continuation lines — must not exceed
160
657
  `SUMMARY_LIMIT`. If the concatenated description exceeds `SUMMARY_LIMIT`,
161
658
  shorten it and move the excess detail into a paragraph after a blank `#` line.
162
659
 
@@ -165,13 +662,13 @@ For example, this tag has a description of 84 characters (within
165
662
  `LINE_LIMIT`) and must be split:
166
663
 
167
664
  ```ruby
168
- # @return [Array] a two-element tuple `[target, options]` containing the translated checkout arguments
665
+ # @return [Array] a two-element array `[target, options]` containing the translated checkout arguments
169
666
  ```
170
667
 
171
668
  Split so each physical line fits within `LINE_LIMIT`:
172
669
 
173
670
  ```ruby
174
- # @return [Array] a two-element tuple `[target, options]` containing the
671
+ # @return [Array] a two-element array `[target, options]` containing the
175
672
  # translated checkout arguments
176
673
  ```
177
674
 
@@ -185,8 +682,8 @@ continuation paragraph — must independently fit within `LINE_LIMIT`
185
682
  (or `LINE_MAX` for unwrappable content such as URLs, long inline code
186
683
  spans, long `[Type]` expressions, `@example` code, or table rows).
187
684
 
188
- These rules apply equally to tag text (`@param`, `@return`, etc.) the first
189
- sentence of a tag is its short description. The no-punctuation rule applies only to
685
+ These rules apply to every doc comment an object's short description and a
686
+ tag's text alike; the first sentence is the short description. The no-punctuation rule applies only to
190
687
  short descriptions; continuation paragraphs use normal prose punctuation (periods).
191
688
  Separate continuation paragraphs with a blank comment line.
192
689
 
@@ -223,13 +720,13 @@ Incorrect — trailing period on title, missing blank line before continuation,
223
720
  # lines were selected (not an error).
224
721
  ```
225
722
 
226
- **`@return` must always include a type**
723
+ #### `@return` must always include a type
227
724
 
228
725
  Every `@return` tag must include a `[Type]` specifier. `@return the value` is
229
726
  incorrect; write `@return [Object] the value` (or a more specific type). If the
230
727
  return value is the block's return value, use `@return [Object]`.
231
728
 
232
- **No shell calls in `@example` blocks**
729
+ #### No shell calls in `@example` blocks
233
730
 
234
731
  Never use backtick shell calls (`` `true` ``, `` `git version` ``) or process-status
235
732
  globals (`$?`, `$CHILD_STATUS`) in `@example` blocks. They are side-effecting,
@@ -252,37 +749,37 @@ Correct:
252
749
  # result = Git::CommandLine::Result.new([], status, '', '')
253
750
  ```
254
751
 
255
- **Blank lines within `@example` blocks**
752
+ #### Blank lines within `@example` blocks
256
753
 
257
754
  Within `@example` blocks, blank comment lines (`#`) render as literal blank lines in
258
755
  the displayed code. Use them for readability between setup and assertions, but be
259
756
  aware they are literal content, not tag separators.
260
757
 
261
- **`@example` titles are required**
758
+ #### `@example` titles are required
262
759
 
263
760
  Every `@example` tag must include a title — the descriptive text on the same line
264
761
  after `@example`. Write `@example Basic usage`, not bare `@example`. Titles appear
265
762
  as headings in generated docs and help readers scan multiple examples.
266
763
 
267
- **Cross-reference links only resolve to objects included in generated docs**
764
+ #### Cross-reference links only resolve to objects included in generated docs
268
765
 
269
766
  YARD renders `{ClassName#method}` as a hyperlink only when the target method is
270
767
  included in the generated documentation. Public objects are included by default,
271
768
  and objects marked with `@api private` remain included with a private annotation.
272
769
  Ruby private methods are excluded by default. Do not write
273
- `{Git::Lib#some_private_method}` — it will render as plain text and may generate
274
- an unresolved reference warning.
770
+ `{Git::Commands::Base#execute_command}` — it will render as plain text and may
771
+ generate an unresolved reference warning.
275
772
 
276
773
  If you need to refer to a private method, describe it in prose instead, or link to
277
774
  the public method that callers should use.
278
775
 
279
- **Inline code formatting**
776
+ #### Inline code formatting
280
777
 
281
778
  Use backtick code spans for inline code (`` `true` ``, `` `nil` ``, symbols, type
282
779
  names, method calls). Do not use the RDoc `+value+` style; it is inconsistent with
283
780
  the project's markdown rendering via redcarpet.
284
781
 
285
- **Escaping `{` in descriptions**
782
+ #### Escaping opening braces in descriptions
286
783
 
287
784
  YARD treats `{` as the start of a cross-reference link. Because redcarpet consumes
288
785
  one `\` before YARD sees it, write `\\{` (two backslashes) to produce a literal
@@ -290,486 +787,177 @@ one `\` before YARD sees it, write `\\{` (two backslashes) to produce a literal
290
787
  `'stash@\\{0}'` to render as `stash@{0}`. Using only `\{` still triggers a YARD
291
788
  unresolved link warning.
292
789
 
293
- **Cross-reference links**
790
+ #### Cross-reference links
294
791
 
295
792
  Link to other code objects anywhere in a doc comment using `{ClassName}`,
296
793
  `{ClassName#method}`, `{#method_in_same_class}`, or `{Class::CONSTANT}`. An
297
794
  optional title follows the reference separated by a space:
298
- `{Git::Base#log the log method}`. Do not use brace syntax inside `@see` tags —
795
+ `{Git::Repository#log the log method}`. Do not use brace syntax inside `@see` tags —
299
796
  `@see` links automatically without braces. `@see` accepts three target forms:
300
797
 
301
- - Code objects: `@see Git::Base#log`
798
+ - Code objects: `@see Git::Repository#log`
302
799
  - URLs: `@see https://git-scm.com/docs/git-log`
303
800
  - Quoted text: `@see "Pro Git, Chapter 2"`
304
801
 
305
- **Type specifier conventions**
802
+ #### Type specifier conventions
306
803
 
307
804
  The `[Types]` field in `@param`, `@return`, `@raise`, etc. supports:
308
805
 
309
- - Plain types: `[String]`, `[Integer]`, `[Git::Base]`
806
+ - Plain types: `[String]`, `[Integer]`, `[Git::Repository]`
310
807
  - Multiple types: `[String, nil]`, `[String, Array<String>]`
311
- - Parametrized types: `[Array<String>]`, `[Hash<Symbol, String>]`
808
+ - Parametrized collections: `[Array<String>]`, `[Hash<Symbol, String>]`
809
+ - Fixed-position tuples: `[Array(String, Integer)]`, `[Array(Symbol, (Integer, nil))]`
312
810
  - Duck-types (responds to): `[#read]`, `[#to_s]`
313
811
  - `[Boolean]` — conventional meta-type for `true` or `false` (not a real Ruby class)
314
812
  - `[void]` — for `@return` tags on methods whose return value must not be used
315
813
 
316
- **`@api private` vs `@private`**
814
+ #### `Array<...>` (collection) vs `Array(...)` (tuple)
815
+
816
+ YARD treats angle brackets and parentheses as distinct type constructors, so
817
+ choose the one that matches the value's shape:
818
+
819
+ - `Array<T>` (angle brackets) — a **collection**: an array *of* `T` with any
820
+ number of elements, e.g. `Array<String>` is zero or more strings. Listing
821
+ several types inside `<...>` means each element is one *of* those types
822
+ (`Array<String, Symbol>` is an array whose elements are each a String or a
823
+ Symbol), **not** a fixed sequence.
824
+ - `Array(A, B)` (parentheses) — a **tuple**: an array *containing* exactly `A`
825
+ then `B` in that order, e.g. `Array(String, Integer)` is a two-element
826
+ `[name, count]`. Use this whenever a method returns or accepts a
827
+ fixed-position array such as `[status, similarity]` or `[path, options]`.
828
+
829
+ The same rule applies to nested types: `Array<Array(Integer, String)>` is a
830
+ collection of `[index, message]` tuples. Use `[Array]` with a prose description
831
+ only when the element types cannot be expressed concisely.
832
+
833
+ #### `@api private` vs `@private`
317
834
 
318
835
  Use `@api private` (not `@private`) to mark internal classes and modules. `@api
319
836
  private` includes the object in generated docs with a private annotation; YARD's
320
837
  `@private` tag excludes the object from docs entirely.
321
838
 
322
- **`@since` do not use**
839
+ #### Class and module `@api` visibility (Required)
840
+
841
+ Every documented class and module must declare API visibility explicitly with
842
+ exactly one tag:
843
+
844
+ - `@api public` for user-facing API
845
+ - `@api private` for internal implementation details
846
+
847
+ Do not rely on YARD's implicit default visibility.
848
+
849
+ `@api` visibility is inherited by child objects. Omit redundant method-level or
850
+ constant-level `@api` tags when a child matches its enclosing class/module
851
+ visibility.
852
+
853
+ Add method-level or constant-level `@api` only when a child intentionally differs
854
+ from its enclosing class/module visibility.
855
+
856
+ #### `@since` tags are not used
323
857
 
324
858
  Do not add `@since` tags. The project has no historical `@since` annotations, and
325
859
  retroactively tagging existing APIs is impractical at v4.x. Version introduction
326
860
  history is tracked through git blame and the CHANGELOG instead.
327
861
 
328
- **`@todo` do not use**
862
+ #### `@todo` tags are not used
329
863
 
330
864
  Do not add `@todo` tags. Track incomplete work in GitHub Issues, not in source
331
865
  comments. YARD renders `@todo` prominently in generated docs, and these annotations
332
866
  go stale quickly.
333
867
 
334
- **`@abstract`**
868
+ #### `@abstract`
335
869
 
336
870
  Use `@abstract` on classes or methods that must be subclassed or overridden before
337
871
  use. Include guidance text describing what the subclass must implement:
338
872
  `@abstract Subclass and implement {#run}`. Do not use `@abstract` on concrete
339
873
  classes or fully implemented methods.
340
874
 
341
- ### Element-Specific Rules
342
-
343
- **Classes**
344
-
345
- - One-sentence class description as a **noun phrase** (or starting with "Represents…") — the description should pass
346
- the "This class is a…" litmus test (i.e. you should be able to prefix "This class
347
- is a" and produce a grammatical sentence). "Represents…" is an accepted convention.
348
- Do not start descriptions with "This class is…", "Provides…", or "Encapsulates…".
349
- - Good: `Wrapper around the git binary`, `Immutable value object for a branch
350
- delete result`, `Represents a git branch`
351
- - Bad: `This class wraps the git binary`, `Provides branch deletion`,
352
- `Encapsulates branch state`
353
- - `@api public` or `@api private` tag to declare visibility — use `@api public` for
354
- stable user-facing classes; use `@api private` for internal implementation classes
355
- (e.g., `Git::Lib`, `Git::Commands::*`, parsers)
356
- - At least one `@example` showing typical instantiation or primary usage — this
357
- applies to all classes including `@api private` classes
358
- - Error/exception classes must also state when the error is raised in class-level
359
- prose, using caller-facing wording such as `Raised when branch deletion fails`
360
- - Deprecated classes must include `@deprecated` explaining the migration path
361
- - When present, class-level tags must appear in this order: `@example`, `@note`,
362
- `@deprecated`, `@see`, `@api`, `@abstract`
363
-
364
- **Modules**
365
-
366
- - One-sentence description — "Namespace for…", "Provides helpers for…", or
367
- "Mixin that adds…"
368
- - `@api public` or `@api private` — use `@api public` for stable user-facing modules;
369
- use `@api private` for internal implementation modules
370
- - No `@example` required unless the module provides standalone methods
371
- - Deprecated modules must include `@deprecated` explaining the migration path
372
- - When present, module-level tags must appear in the same order as class-level
373
- tags: `@example`, `@note`, `@deprecated`, `@see`, `@api`
374
-
375
- **Constants**
376
-
377
- - A comment immediately above the constant describing its purpose and valid values
378
- - No special YARD tag is needed; YARD picks up the preceding comment automatically
379
- - Add `# @return [Type]` when the constant holds a collection, frozen structure, or
380
- domain-specific type whose shape is not immediately obvious from the value
381
-
382
- **Attributes**
383
-
384
- - For explicitly written `attr_reader`, `attr_accessor`, and `attr_writer` declarations,
385
- place the documentation directly above the attribute; do **not** use the `@!attribute`
386
- directive
387
- - For dynamically created attributes, `Data.define` members, or `Struct.new`
388
- members, you **must** use a `# @!attribute [r/rw/w] name` YARD directive
389
- - Must include `@return [Type] description` explaining the value and its units or
390
- constraints if relevant
391
- - For explicit `attr_reader`/`attr_accessor`/`attr_writer`, include a short
392
- description paragraph above the attribute in addition to `@return`
393
- - For `@!attribute` directives (in `Data.define` / `Struct.new`), the `@return`
394
- tag inside the directive block serves as the sole documentation — no separate
395
- short description is needed
396
- - Tags inside `@!attribute` (and `@!method`) directive blocks must be indented
397
- two extra spaces relative to the directive itself
398
- - Must be defined at the class level, not inside method bodies
399
-
400
- **Dynamically defined methods (`@!method`)**
401
-
402
- Use the `# @!method name(params)` directive for methods created via
403
- metaprogramming (`define_method`, method-generating DSLs, etc.) that have no
404
- literal `def`. Place the directive and its doc comment where the method would
405
- logically appear in the class body. Tags inside the directive block follow the
406
- same indentation rule as `@!attribute` — indented two extra spaces relative to
407
- the directive.
408
-
409
- **`Data.define` classes**
410
-
411
- Immutable value objects defined with `Data.define` use the following conventions
412
- (see `Git::BranchDeleteFailure` for a canonical example):
413
-
414
- - Class-level doc: noun-phrase short description, `@example`, `@see`, `@api`
415
- - One `@!attribute [r]` directive per member with `@return [Type] description`
416
- - Attribute directives are placed after class-level tags and before the
417
- `Data.define` line
418
- - Custom methods defined inside the `Data.define` block follow standard method
419
- rules
420
-
421
- **`Struct.new` classes**
422
-
423
- Document `Struct.new` classes using the same conventions as `Data.define` classes:
424
- class-level doc with a noun-phrase short description, `@example`, `@see`, `@api`,
425
- and one `@!attribute` directive per member with `@return [Type] description`.
426
-
427
- ```ruby
428
- # Immutable value object for a failed branch delete
429
- #
430
- # @example Create a failure object
431
- # failure = Git::BranchDeleteFailure.new(name: 'feature', result: result)
432
- # failure.name #=> "feature"
433
- # failure.result #=> #<Git::CommandLineResult ...>
434
- #
435
- # @see Git::BranchDeleteResult
436
- #
437
- # @api public
438
- #
439
- # @!attribute [r] name
440
- #
441
- # @return [String] the branch name that failed to delete
442
- #
443
- # @!attribute [r] result
444
- #
445
- # @return [Git::CommandLineResult] the result of the failed delete
446
- #
447
- BranchDeleteFailure = Data.define(:name, :result)
448
- ```
449
-
450
- **Methods**
451
-
452
- - All methods must have a short description that:
453
- - Starts with a verb (`Returns`, `Resets`, `Finds` — not "The…" or "This method…")
454
- - Omits the subject — write "Returns the commit count", not "This method returns
455
- the commit count"
456
- - States the outcome, not the mechanism — `Finds the nearest tagged ancestor` not
457
- `Iterates through commits checking tags`
458
- - Mentions key parameters inline — `Resets HEAD to the given ref` rather than
459
- relying solely on param tags
460
- - Avoids restating the method name — add specificity about what kind, from where,
461
- or what is returned
462
- - Is specific about return values — `Returns true if the branch exists, false
463
- otherwise` beats `Returns a Boolean`
464
- - Omits implementation details — callers don't care about internal loops or temp
465
- variables
466
- - Methods use these standard YARD tags:
467
- - `@param` for each method parameter, in signature order; omit `@param` entirely
468
- on zero-argument methods
469
- - `@return` on every method; use `[void]` when the return value must not be used
470
- - `@raise` for each caller-relevant exception the method can raise as part of its
471
- contract; omit `@raise` when the method has no documented exceptional path
472
- - Methods without Ruby `private` visibility must have one or more `@example`s;
473
- Ruby-private methods may omit `@example` unless usage would otherwise be unclear
474
- - Methods that yield to a block must include `@yield [param_names]`, one
475
- `@yieldparam name [Type]` per yielded parameter, and `@yieldreturn [Type]`; omit
476
- all yield tags on methods that do not yield
477
- - Use `@overload` when a method has distinct call signatures with different
478
- parameters or return types — each overload gets its own full set of tags.
479
- Methods that yield only when an optional block is given should use `@overload`
480
- to document the with-block and without-block signatures separately
481
- - Methods whose signature uses an **anonymous keyword splat** (`**`),
482
- **anonymous positional splat** (`*`), or the **argument forwarding
483
- parameter** (`...`) must document their call shapes with `@overload` blocks
484
- that name the parameters. `@param`, `@option`, `@yield`, and `@yieldparam`
485
- cannot bind to an anonymous splat or to `...` — the named overload signature
486
- is what gives YARD a parameter to attach the docs to. Do **not** introduce a
487
- named splat (or expand `...` into `*args, **kwargs, &block`) solely so the
488
- tags will bind; that conflicts with RuboCop's `Style/ArgumentsForwarding`
489
- cop, and the `@overload` form satisfies both
490
- - Use `@note` for callouts that need visual emphasis: thread-safety warnings,
491
- significant side effects, or platform-specific behaviour
492
- - Deprecated methods must include `@deprecated` explaining the migration path,
493
- e.g. `@deprecated Use {#new_method} instead`
494
- - `@api` is optional on methods — when omitted, the method inherits the containing
495
- class's `@api` level. Use it only when the method's intended visibility differs
496
- from the class's level (e.g. an `@api private` helper inside an `@api public`
497
- class)
498
-
499
- ## Step 1: Identify What Needs Documentation
500
-
501
- ```bash
502
- # Find undocumented objects
503
- bundle exec yard stats --list-undoc
504
-
505
- # Check a specific file
506
- bundle exec yard doc lib/git/base.rb --no-output
507
- ```
508
-
509
- ## Step 2: Write Documentation
510
-
511
- Follow the YARD documentation templates below. Use the **standard template** when a
512
- method has a single call signature. Use the **overload template** when a method has
513
- distinct call signatures with different parameters or return types.
875
+ ### Method Rules
514
876
 
515
- When `@overload` blocks are present:
516
-
517
- - Keep `@param`, `@option`, and `@return` inside overload blocks only
518
- - Keep overload-specific `@raise` inside the relevant overload block
519
- - Keep shared `@raise` at top level only once (do not duplicate inside overloads)
520
- - Keep non-signature tags (`@note`, `@deprecated`, `@see`, `@api`) at top level
521
-
522
- Avoid duplicating the same `@raise` at both top level and overload level. This
523
- causes conflicting or noisy generated docs.
877
+ #### Short description
524
878
 
525
- **Trigger: always use `@overload` when the signature contains `*`, `**`, or `...`**
879
+ Every method must have a short description that:
526
880
 
527
- Anonymous splats and the forwarding parameter give `@param`, `@option`, `@yield`,
528
- and `@yieldparam` no named parameter to bind to. YARD silently drops or
529
- mis-renders these tags when the signature is, for example, `def foo(**)` or
530
- `def foo(paths = '.', **)` even though `paths` is named, the keyword options
531
- have no name so every `@option` is unbound. As soon as any parameter in the
532
- signature is anonymous (`*`, `**`, or `...`), switch to `@overload` for the entire
533
- signature (see [Documenting anonymous splats with `@overload`](#documenting-anonymous-splats-with-overload)).
881
+ - Starts with a verb (`Returns`, `Resets`, `Finds` — not "The…" or "This method…")
882
+ - Omits the subject write "Returns the commit count", not "This method returns
883
+ the commit count"
884
+ - States the outcome, not the mechanism `Finds the nearest tagged ancestor` not
885
+ `Iterates through commits checking tags`
886
+ - Mentions key parameters inline `Resets HEAD to the given ref` rather than
887
+ relying solely on param tags
888
+ - Avoids restating the method name — add specificity about what kind, from where,
889
+ or what is returned
890
+ - Is specific about return values — `Returns true if the branch exists, false
891
+ otherwise` beats `Returns a Boolean`
892
+ - Omits implementation details — callers don't care about internal loops or temp
893
+ variables
534
894
 
535
- ### Standard template (no `@overload`)
895
+ #### Standard tags
536
896
 
537
- When present, tags must appear in the order shown. `@param` tags appear in
538
- parameter order; `@option` tags appear immediately after the `@param` for the hash
539
- they describe. Every `@option` tag **must** be preceded by a `@param` for the
540
- options hash, and all `@option` tags under that `@param` must reference the same
541
- parameter name. For keyword arguments (`**options` or `**kwargs`), use
542
- `@param options [Hash]` (or the actual splat name) as the preceding `@param`:
897
+ Methods use these standard YARD tags:
543
898
 
544
- ```ruby
545
- # Short description of what the method does
546
- #
547
- # Longer description with more details about behavior,
548
- # edge cases, or important notes.
549
- #
550
- # @example Basic usage
551
- # git = Git.open('/path/to/repo')
552
- # result = git.method_name('arg')
553
- #
554
- # @example With options
555
- # git.method_name('arg', option: true)
556
- #
557
- # @param name [Type] description of parameter
558
- #
559
- # @param options [Hash] options hash description
560
- #
561
- # @option options [Type] :key description of option
562
- #
563
- # @param path [String] a parameter after the options hash
564
- #
565
- # @return [Type] description of return value
566
- #
567
- # @raise [ArgumentError] when invalid arguments are provided
568
- #
569
- # @raise [Git::FailedError] when git exits with a non-zero exit status
570
- #
571
- # @yield [commit] passes each commit to the block
572
- #
573
- # @yieldparam commit [Git::Object::Commit] a commit object
574
- #
575
- # @yieldreturn [void]
576
- #
577
- # @note This method is not thread-safe
578
- #
579
- # @deprecated Use {#new_method} instead
580
- #
581
- # @see #related_method
582
- #
583
- # @see Git::RelatedClass
584
- #
585
- # @see https://git-scm.com/docs/git-log
586
- #
587
- # @api public
588
- #
589
- def method_name(name, options = {})
590
- end
591
- ```
899
+ - `@param` for each method parameter, in signature order; omit `@param` entirely
900
+ on zero-argument methods
901
+ - `@return` on every method; use `[void]` when the return value must not be used
902
+ - `@raise` for each caller-relevant exception the method can raise as part of its
903
+ contract; omit `@raise` when the method has no documented exceptional path
592
904
 
593
- ### Overload template
905
+ #### `@example` on non-private methods
594
906
 
595
- Each `@overload` block carries its own `@example`, `@param`, `@option`, `@return`,
596
- `@raise`, `@yield`, `@yieldparam`, and `@yieldreturn` tags. Tags that are
597
- **not** call-signature-specific — `@note`, `@deprecated`, `@see`, `@api` — remain
598
- at the top level:
907
+ Methods without Ruby `private` visibility must have one or more `@example`s;
908
+ Ruby-private methods may omit `@example` unless usage would otherwise be unclear.
599
909
 
600
- ```ruby
601
- # Short description of what the method does
602
- #
603
- # Longer description with more details about behavior,
604
- # edge cases, or important notes.
605
- #
606
- # @overload method_name(arg)
607
- #
608
- # Single-argument form description
609
- #
610
- # @example Basic usage
611
- # result = git.method_name('arg')
612
- #
613
- # @param arg [String] the argument
614
- #
615
- # @return [String] the result
616
- #
617
- # @overload method_name(arg, options)
618
- #
619
- # Two-argument form description
620
- #
621
- # @example With options
622
- # result = git.method_name('arg', force: true)
623
- #
624
- # @param arg [String] the argument
625
- #
626
- # @param options [Hash] additional options
627
- #
628
- # @return [Array<String>] the results
629
- #
630
- # @note This method is not thread-safe
631
- #
632
- # @deprecated Use {#new_method} instead
633
- #
634
- # @see #related_method
635
- #
636
- # @see https://git-scm.com/docs/git-log
637
- #
638
- # @api public
639
- #
640
- def method_name(name, options = {})
641
- end
642
- ```
910
+ #### Yield tags
643
911
 
644
- ### Overload decision matrix
912
+ Methods that yield to a block must include `@yield [param_names]`, one
913
+ `@yieldparam name [Type]` per yielded parameter, and `@yieldreturn [Type]`; omit
914
+ all yield tags on methods that do not yield.
645
915
 
646
- Use this matrix to decide whether to use `@overload` and where to place tags:
916
+ #### `@overload` for distinct signatures
647
917
 
648
- | Method signature or behavior | Documentation form |
649
- | --- | --- |
650
- | Single named signature, no `*`/`**`/`...` | Standard template (no `@overload`) |
651
- | Uses anonymous `*`, `**`, or `...` | `@overload` required |
652
- | Multiple call shapes (different params and/or return types) | One `@overload` per shape |
653
- | Shared errors across all call shapes | Top-level `@raise` once |
654
- | Error only for specific call shape | `@raise` only in that overload |
918
+ Use `@overload` when a method has distinct call signatures with different
919
+ parameters or return types — each overload gets its own full set of tags.
920
+ Methods that yield only when an optional block is given should use `@overload`
921
+ to document the with-block and without-block signatures separately.
655
922
 
656
- For overload docs, keep `@param`/`@option`/`@return` in overload blocks. Use
657
- top-level `@raise` only for errors that apply to every overload.
923
+ #### `@overload` for anonymous splats
658
924
 
659
- ### Documenting anonymous splats with `@overload`
925
+ Methods whose signature uses an anonymous `*`, `**`, or `...` must document their
926
+ call shapes with named `@overload` blocks. Do **not** name the splat or expand
927
+ `...` into `*args, **kwargs, &block` to make tags bind — that conflicts with
928
+ RuboCop's `Style/ArgumentsForwarding` cop. See
929
+ [Documenting anonymous splats with `@overload`](#documenting-anonymous-splats-with-overload).
660
930
 
661
- When the method signature uses an anonymous splat — `def foo(*)`, `def foo(**)`,
662
- `def foo(*, **)` — or the argument forwarding parameter `def foo(...)` —
663
- `@param`, `@option`, `@yield`, and `@yieldparam` tags have no parameter name
664
- to bind to. RuboCop's `Style/ArgumentsForwarding` cop prefers these forms when
665
- arguments are forwarded unchanged, so naming the splat (or expanding `...`
666
- into `*args, **kwargs, &block`) is **not** an acceptable workaround. Use
667
- `@overload` blocks that introduce named parameters for documentation purposes
668
- only:
931
+ #### `@note` for callouts (Optional)
669
932
 
670
- ```ruby
671
- # Update the index with the current content found in the working tree
672
- #
673
- # @overload add(paths = '.', **options)
674
- #
675
- # @example Stage a specific file
676
- # git.add('README.md')
677
- #
678
- # @param paths [String, Array<String>] file(s) to add (relative to the
679
- # worktree root); defaults to `'.'` (all files)
680
- #
681
- # @param options [Hash] command options
682
- #
683
- # @option options [Boolean, nil] :all (nil) add, modify, and remove index entries to
684
- # match the worktree
685
- #
686
- # @option options [Boolean, nil] :force (nil) allow adding otherwise ignored files
687
- #
688
- # @return [String] the command output
689
- #
690
- # @raise [Git::FailedError] if `git add` exits with a non-zero status
691
- #
692
- def add(paths = '.', **)
693
- Git::Commands::Add.new(@execution_context).call(*Array(paths), **).stdout
694
- end
695
- ```
933
+ Use `@note` for callouts that need visual emphasis: thread-safety warnings,
934
+ significant side effects, or platform-specific behavior.
696
935
 
697
- The same approach applies to `...`. The overload signature names the
698
- parameters; the actual `def` keeps `...` so RuboCop is satisfied:
936
+ #### `@deprecated` on deprecated methods
699
937
 
700
- ```ruby
701
- # Run a command against the underlying execution context
702
- #
703
- # @overload run(command, *args, **options, &block)
704
- #
705
- # @example Run git status
706
- # result = git.run('status')
707
- #
708
- # @param command [String] the git subcommand to run
709
- #
710
- # @param args [Array<String>] positional arguments forwarded to the command
711
- #
712
- # @param options [Hash] keyword options forwarded to the command
713
- #
714
- # @return [Git::CommandLineResult] the command result
715
- #
716
- # @yield [result] yields the command result, when a block is given
717
- #
718
- # @yieldparam result [Git::CommandLineResult] the command result
719
- #
720
- # @yieldreturn [void]
721
- #
722
- def run(command, ...)
723
- Git::Commands::Run.new(@execution_context).call(command, ...)
724
- end
725
- ```
938
+ Deprecated methods must include `@deprecated` explaining the migration path,
939
+ e.g. `@deprecated Use {#new_method} instead`.
726
940
 
727
- When a method has multiple genuinely distinct call shapes, write one
728
- `@overload` block per shape as in the [Overload template](#overload-template)
729
- above.
941
+ #### `@api` on methods (Optional)
730
942
 
731
- **Anonymous block parameter (`&`)** is **not** covered by this rule.
732
- `@yield`, `@yieldparam`, and `@yieldreturn` describe what is yielded to the
733
- block, not the block parameter itself, so they bind correctly even with an
734
- anonymous `&`. Use a named block parameter (`&block`) and a `@param block
735
- [Proc]` tag only in the rare case where the block is documented as a
736
- first-class `Proc` value (stored, returned, or passed elsewhere) rather than
737
- yielded to.
943
+ Method-level `@api` is exception-only: when omitted, the method inherits the
944
+ containing class's `@api` level. Use it only when the method's intended visibility
945
+ differs from the class's level (e.g. an `@api private` helper inside an `@api
946
+ public` class). For overloaded methods, place `@api` once at top level and never
947
+ nest it inside an `@overload` block.
738
948
 
739
- ## Step 3: Verify Documentation
949
+ ## Command Reference
740
950
 
741
951
  ```bash
742
- # Generate and review docs
743
- bundle exec yard doc
744
- open doc/index.html
745
-
746
- # Check for warnings
747
- bundle exec yard doc 2>&1 | grep -i "warn"
748
- ```
749
-
750
- Verify `@example` code runs correctly in `bundle exec bin/console`.
751
- Check that all `@see` references point to valid targets.
952
+ # Lint YARD documentation against the project standards
953
+ bundle exec yard-lint lib/
752
954
 
753
- **Review checklist tag line length**
955
+ # Lint only changed files (great for pre-commit / CI)
956
+ bundle exec yard-lint lib/ --diff main
754
957
 
755
- For every `@param`, `@return`, `@raise`, `@option`, `@yield`, `@yieldparam`,
756
- and `@yieldreturn` tag, check both limits:
958
+ # Show documentation coverage statistics
959
+ bundle exec yard-lint lib/ --stats
757
960
 
758
- 1. **`LINE_LIMIT`**: Count every character from column 1 (indentation, `#`,
759
- metadata, text) on each physical line. If any wrappable line exceeds
760
- `LINE_LIMIT`, split at a word boundary onto a continuation line (indented
761
- two extra spaces). Apply this check to every continuation line
762
- independently. Lines containing URLs, long inline code spans, long `[Type]`
763
- expressions, `@example` code, or markdown table rows may extend up to
764
- `LINE_MAX`.
765
- 2. **`SUMMARY_LIMIT`**: Strip `# ` from each continuation line and join
766
- with a single space. If the concatenated description exceeds
767
- `SUMMARY_LIMIT`, shorten it and move the excess into a paragraph after
768
- a blank `#` line.
769
-
770
- ## Command Reference
771
-
772
- ```bash
773
961
  # Generate documentation
774
962
  bundle exec yard doc
775
963
 
@@ -783,11 +971,11 @@ bundle exec yard stats
783
971
  bundle exec yard stats --list-undoc
784
972
 
785
973
  # Generate docs for specific file
786
- bundle exec yard doc lib/git/base.rb
974
+ bundle exec yard doc lib/git/repository.rb
787
975
 
788
976
  # Check for YARD syntax errors
789
977
  bundle exec yard doc --no-output 2>&1
790
978
 
791
979
  # View documentation for specific class
792
- bundle exec yard ri Git::Base
980
+ bundle exec yard ri Git::Repository
793
981
  ```