git 4.0.6 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2705 @@
1
+ # GitHub Copilot Instructions for ruby-git
2
+
3
+ ## Project Overview
4
+
5
+ ruby-git is a Ruby gem that provides a Ruby interface to Git repositories.
6
+
7
+ The git gem wraps system calls to the `git` command line and provides an API to:
8
+
9
+ - Create, read, and manipulate Git repositories
10
+ - Work with branches, commits, tags, and remotes
11
+ - Inspect repository history and objects
12
+ - Perform Git operations like merge, clone, fetch, push, etc.
13
+ - Handle complex interactions including branching, merging, and patch generation
14
+
15
+ **Current Status:** Stable project supporting Ruby 3.2.0+ minimum and Git 2.28.0+.
16
+ Compatible with MRI Ruby 3.2+ on Mac, Linux, and Windows.
17
+
18
+ ## AI Use Cases
19
+
20
+ This document guides AI agents in handling the following types of tasks. Each
21
+ category includes a link to the workflow that should be followed.
22
+
23
+ ### Issue Triage & Investigation
24
+
25
+ **→ Use [Development Workflow](#development-workflow) (Phase 0: TRIAGE only -- do not proceed to implementation)**
26
+
27
+ - **"Diagnose issue #999"** - Investigate reported issues, identify root causes, and
28
+ report findings without implementing changes
29
+ - **"Is issue #999 a bug or feature request?"** - Analyze and categorize issues
30
+ - **"Check if issue #999 is a duplicate"** - Search for similar existing issues
31
+ - **"Respond to issue #999"** - Answer questions or provide clarification on issues
32
+
33
+ ### Bug Fixes
34
+
35
+ **→ Use [Development Workflow](#development-workflow) (Phases 0-3: TRIAGE → PREPARE → EXECUTE → FINALIZE)**
36
+
37
+ - **"Fix issue #999"** - Implement a fix for a reported bug following the full TDD
38
+ workflow (diagnose → implement → test → PR)
39
+ - **"Fix the timeout handling in Git::CommandLine"** - Address specific bugs in the
40
+ codebase
41
+
42
+ ### Feature Implementation
43
+
44
+ **→ Use [Development Workflow](#development-workflow) (Phases 0-3: TRIAGE → PREPARE → EXECUTE → FINALIZE)**
45
+
46
+ - **"Implement issue #999"** - Build new features requested in issues
47
+ - **"Add support for git worktree commands"** - Implement specific functionality
48
+ - **"Implement the feature requested in issue #999 and create a PR"** - Full
49
+ implementation workflow ending with PR creation
50
+
51
+ ### Code Improvements
52
+
53
+ **→ Use [Development Workflow](#development-workflow) (Phases 1-3: PREPARE → EXECUTE → FINALIZE)**
54
+
55
+ - **"Refactor the Git::Branch class to reduce duplication"** - Improve code quality
56
+ without changing behavior
57
+ - **"Add missing YARD documentation to Git::Base methods"** - Enhance documentation
58
+ - **"Add tests for Git::Remote#fetch"** - Improve test coverage
59
+
60
+ ### Pull Request Review
61
+
62
+ **→ Use [Pull Request Review Workflow](#pull-request-review-workflow)**
63
+
64
+ - **"Review PR #999"** - Review a pull request, analyze changes against project
65
+ standards, and post review comments
66
+ - **"Review PR #999 and approve if it looks good"** - Perform review with potential
67
+ approval
68
+ - **"Check if PR #999 follows our coding standards"** - Focused review on specific
69
+ criteria
70
+
71
+ ### Maintenance Tasks
72
+
73
+ **→ Use [Development Workflow](#development-workflow) (Phases 1-3: PREPARE → EXECUTE → FINALIZE)**
74
+
75
+ - **"Update Ruby version support"** - Modify compatibility requirements
76
+ - **"Fix rubocop violations in lib/git/base.rb"** - Address linting issues
77
+ - **"Run the test suite and fix any failures"** - Ensure code quality
78
+
79
+ ### Dependency Management
80
+
81
+ **→ Use [Dependency Management Workflow](#dependency-management-workflow)**
82
+
83
+ - **"Update all gem dependencies"** - Update dependencies to latest versions
84
+ - **"Check for outdated dependencies"** - List gems that have newer versions available
85
+ - **"Fix security vulnerabilities in dependencies"** - Address CVEs and security issues
86
+ - **"Update \<gem-name\> to version X.Y.Z"** - Update a specific dependency
87
+
88
+ ### Test Debugging & Maintenance
89
+
90
+ **→ Use [Test Debugging & Maintenance Workflow](#test-debugging--maintenance-workflow)**
91
+
92
+ - **"Why is test_branch failing?"** - Debug consistently failing tests
93
+ - **"Fix flaky test in test_remote.rb"** - Address intermittent test failures
94
+ - **"Debug intermittent test failure"** - Investigate non-deterministic test behavior
95
+ - **"Improve test coverage for Git::Base#add"** - Add missing tests for existing code
96
+
97
+ ### CI/CD Troubleshooting
98
+
99
+ **→ Use [CI/CD Troubleshooting Workflow](#cicd-troubleshooting-workflow)**
100
+
101
+ - **"Why is CI failing on PR #999?"** - Diagnose CI/CD failures and report root causes
102
+ - **"Fix the failing GitHub Actions build"** - Investigate and resolve CI failures
103
+ - **"Debug test failures in CI for PR #999"** - Identify why tests pass locally but fail in CI
104
+ - **"Check CI status for this branch"** - View current build status
105
+
106
+ ### Code Review & Analysis
107
+
108
+ **→ No specific workflow required (use standard code analysis techniques)**
109
+
110
+ - **"Review the changes in this file"** - Analyze code quality and suggest
111
+ improvements
112
+ - **"Explain how Git::CommandLine handles timeouts"** - Provide code explanations
113
+ - **"What would break if we change this method signature?"** - Impact analysis
114
+
115
+ ### Merge Conflict Resolution
116
+
117
+ **→ Use [Merge Conflict Resolution Workflow](#merge-conflict-resolution-workflow)**
118
+
119
+ - **"Resolve merge conflicts in PR #999"** - Help resolve conflicts in a pull request
120
+ - **"Help merge feature branch into main"** - Assist with branch merging and conflict
121
+ resolution
122
+ - **"Show merge conflicts between branches"** - Identify conflicting changes before
123
+ merging
124
+
125
+ ### Code Archaeology & History Analysis
126
+
127
+ **→ Use [Code Archaeology & History Analysis Workflow](#code-archaeology--history-analysis-workflow)**
128
+
129
+ - **"When was this bug introduced?"** - Use git bisect to find the commit that
130
+ introduced a bug
131
+ - **"Find all callers of Git::Base#checkout"** - Search codebase for method usage
132
+ - **"Show the history of this method"** - Track changes to specific code over time
133
+ - **"Who last changed this file?"** - Use git blame to identify recent contributors
134
+ - **"What changed in this file between v1.0 and v2.0?"** - Compare file history
135
+ across versions
136
+
137
+ ### Release Management
138
+
139
+ **→ Use [Release Management Workflow](#release-management-workflow)**
140
+
141
+ - **"Prepare a new release"** - Guide through version bump, changelog, and release
142
+ process
143
+ - **"Generate release notes from recent PRs"** - Compile changes since last release
144
+ - **"What PRs are included in this release?"** - List merged PRs between versions
145
+ - **"Tag and publish a release"** - Create git tags and publish gem
146
+ - **"Check release readiness"** - Verify all checks pass before release
147
+
148
+ ### Breaking Change Analysis
149
+
150
+ **→ Use [Breaking Change Analysis Workflow](#breaking-change-analysis-workflow)**
151
+
152
+ - **"What would break if we remove this method?"** - Assess impact of deprecation
153
+ - **"Find all usages of deprecated API"** - Search for code using deprecated features
154
+ - **"Assess impact of changing this interface"** - Analyze downstream effects of API
155
+ changes
156
+ - **"List all public API methods"** - Enumerate the public interface for audit
157
+
158
+ ### Documentation Tasks
159
+
160
+ **→ Use [Documentation Workflow](#documentation-workflow)**
161
+
162
+ - **"Generate missing YARD documentation"** - Add documentation to undocumented
163
+ methods
164
+ - **"Update README examples to match current API"** - Keep examples current
165
+ - **"Fix documentation errors"** - Correct inaccurate or outdated documentation
166
+ - **"Document this class/method"** - Add comprehensive YARD documentation
167
+ - **"Check documentation coverage"** - Identify undocumented public methods
168
+
169
+ ## Architecture & Module Organization
170
+
171
+ The codebase is structured to separate high-level API interactions from low-level
172
+ command execution, ensuring maintainability and testability. ruby-git follows a
173
+ modular architecture:
174
+
175
+ - **Git::Base** - Main interface for repository operations (most major actions)
176
+ - **Git::Lib** - Low-level Git command execution via system calls
177
+ - **Git::CommandLine** - Handles Git command construction and execution with timeout
178
+ support
179
+ - **Git Objects** - Repository objects (Commit, Tree, Blob, Tag) via `Git::Object`
180
+ - **Git::Status** - Working directory status (tracked/untracked/modified files)
181
+ - **Git::Diff** - Diff operations returning file-level patches and statistics
182
+ - **Git::Log** - Enumerable query builder for commit history
183
+ - **Git::Branch/Branches** - Branch management (local and remote)
184
+ - **Git::Remote** - Remote repository references
185
+ - **Git::Worktree/Worktrees** - Git worktree support
186
+ - **Git::Stash/Stashes** - Stash management
187
+
188
+ Key directories:
189
+
190
+ - `lib/git/` - Core library code
191
+ - `tests/units/` - Test::Unit test suite
192
+ - `doc/` - YARD-generated documentation
193
+ - `pkg/` - Built gem packages
194
+ - `redesign/` - Architecture redesign documentation
195
+
196
+ ## Coding Standards
197
+
198
+ High-quality code is essential for the long-term maintenance of this library. Adhere
199
+ to the following standards to ensure consistency, readability, and reliability across
200
+ the codebase.
201
+
202
+ ### Ruby Style
203
+
204
+ To ensure code consistency and leverage modern Ruby features, adhere to the following
205
+ style guidelines:
206
+
207
+ - Use `frozen_string_literal: true` at the top of all Ruby files
208
+ - Follow Ruby community style guide (Rubocop-compatible)
209
+ - Require Ruby 3.2.0+ features and idioms
210
+ - Use keyword arguments for methods with multiple parameters
211
+ - Prefer `private` over `private :method_name` for method visibility
212
+ - Use pattern matching for complex conditional logic where appropriate
213
+
214
+ ### Code Organization
215
+
216
+ To maintain a clean, modular, and navigable codebase, structure your code according
217
+ to these principles:
218
+
219
+ - Keep classes focused and single-responsibility
220
+ - Use modules for mixins and namespace organization
221
+ - Place related classes in the same file only if they're tightly coupled
222
+ - One public class per file as a general rule
223
+ - Core library code organized in `lib/git/` directory
224
+
225
+ ### Naming Conventions
226
+
227
+ Follow these naming conventions to ensure code readability and consistency with the
228
+ existing codebase and idiomatic Ruby:
229
+
230
+ - Classes/Modules: PascalCase (e.g., `Git::Base`, `Git::Branch`, `Git::CommandLine`)
231
+ - Methods/variables: snake_case (e.g., `current_branch`, `ls_files`, `commit_all`)
232
+ - Constants: UPPER_SNAKE_CASE (e.g., `VERSION`)
233
+ - Predicate methods: end with `?` (e.g., `bare?`, `success?`, `exist?`)
234
+ - Dangerous methods: end with `!` if they modify in place
235
+ - Instance variables: `@variable_name`
236
+ - Avoid class variables; prefer class instance variables or constants
237
+
238
+ ## Design Philosophy
239
+
240
+ **Note:** As of v2.x, this design philosophy is aspirational. Future versions may
241
+ include interface changes to fully align with these principles.
242
+
243
+ The git gem is designed as a lightweight wrapper around the `git` command-line tool,
244
+ providing a simple and intuitive Ruby interface for programmatically interacting with
245
+ Git.
246
+
247
+ ### Principle of Least Surprise
248
+
249
+ The design should prioritize predictability and familiarity for users already
250
+ accustomed to the Git command line:
251
+
252
+ - Do not introduce unnecessary abstraction layers
253
+ - Do not modify Git's core functionality
254
+ - Maintain close alignment with the existing `git` command-line interface
255
+ - Avoid extensions or alterations that could lead to unexpected behaviors
256
+ - Allow users to leverage their existing knowledge of Git
257
+
258
+ ### Direct Mapping to Git Commands
259
+
260
+ To maintain clarity and ease of use, the API should mirror the underlying Git
261
+ commands as closely as possible:
262
+
263
+ - Git commands are implemented within the `Git::Base` class
264
+ - Each method should directly correspond to a `git` command
265
+ - Example: `git add` → `Git::Base#add`, `git ls-files` → `Git::Base#ls_files`
266
+ - When a single Git command serves multiple distinct purposes, use the command name
267
+ as a prefix followed by a descriptive suffix
268
+ - Example: `#ls_files_untracked`, `#ls_files_staged`
269
+ - Introduce aliases to provide more user-friendly method names where appropriate
270
+
271
+ ### Parameter Naming
272
+
273
+ Adopt a naming strategy that reinforces the connection to the Git CLI:
274
+
275
+ - Parameters are named after their corresponding long command-line options
276
+ - Ensures familiarity for developers already accustomed to Git
277
+ - Note: Not all Git command options are supported
278
+
279
+ ### Output Processing
280
+
281
+ To provide a rich and idiomatic Ruby experience, process raw Git output into
282
+ structured objects when the output is important to the user:
283
+
284
+ - Translate Git command output into Ruby objects for easier programmatic use
285
+ - Ruby objects often include methods that allow for further Git operations
286
+ - Provide additional functionality while staying true to underlying Git behavior
287
+
288
+ ### User Documentation
289
+
290
+ Comprehensive documentation is essential for a public library. Follow these
291
+ guidelines:
292
+
293
+ - Use YARD syntax for all public methods
294
+ - Include `@param`, `@return`, `@raise`, `@example` tags
295
+ - Document edge cases, platform differences, and security considerations
296
+ - Keep method documentation up-to-date with implementation
297
+ - Add `@api private` for internal-only methods
298
+ - Document Git version requirements and compatibility
299
+
300
+ Example:
301
+
302
+ ```ruby
303
+ # Opens a Git repository
304
+ #
305
+ # @param [String, Pathname] path The path to the working directory or .git directory
306
+ # @param [Hash] options The options for this command (see list of valid options below)
307
+ # @option options [Logger] :log A logger to use for Git operations
308
+ # @option options [Numeric] :timeout Maximum seconds to wait for Git commands (0 for no timeout)
309
+ # @return [Git::Base] an object that can execute git commands in the context of the repository
310
+ # @raise [ArgumentError] if path is not a valid Git repository
311
+ # @example Open a repository
312
+ # git = Git.open('/path/to/repo')
313
+ # puts git.log.first.message
314
+ # @api public
315
+ def self.open(path, options = {})
316
+ # implementation
317
+ end
318
+ ```
319
+
320
+ ## Key Technical Details
321
+
322
+ This section outlines the critical technical mechanisms that power the gem.
323
+ Understanding these details is important for implementing new features or debugging
324
+ complex issues.
325
+
326
+ ### Git Command Execution
327
+
328
+ All Git commands are executed through the `Git::CommandLine` class which:
329
+
330
+ - Constructs Git commands with proper argument escaping
331
+ - Handles environment variables and working directory context
332
+ - Manages command execution with timeout support
333
+ - Captures stdout, stderr, and exit status
334
+ - Raises appropriate errors on command failures
335
+
336
+ ### Major Classes and Their Responsibilities
337
+
338
+ Understanding the core classes is crucial for navigating the codebase and ensuring
339
+ logic is placed correctly. The following list outlines the primary classes and their
340
+ specific responsibilities:
341
+
342
+ 1. **Git::Base**: The main repository interface
343
+ - Entry point for most Git operations
344
+ - Delegates to `Git::Lib` for low-level operations
345
+ - Manages working directory, index, and repository references
346
+ - Returns domain objects (Branch, Status, Diff, Log, etc.)
347
+
348
+ 2. **Git::Lib**: Low-level command execution
349
+ - Executes Git commands via `Git::CommandLine`
350
+ - Parses Git command output
351
+ - Minimal business logic - focuses on command execution
352
+
353
+ 3. **Git::CommandLine**: Command execution layer
354
+ - Builds Git command arrays with proper escaping
355
+ - Manages subprocess execution with timeout support
356
+ - Handles timeout and error conditions
357
+ - Returns `Git::CommandLineResult` with output and status
358
+
359
+ 4. **Git Objects** (Commit, Tree, Blob, Tag)
360
+ - Immutable representations of Git objects
361
+ - Lazy-loaded from repository
362
+ - Methods for inspecting object properties and relationships
363
+
364
+ 5. **Git::Status**: Working directory status
365
+ - Enumerable collection of `Git::Status::StatusFile`
366
+ - Tracks added, changed, deleted, and untracked files
367
+ - Similar to `git status` command output
368
+
369
+ 6. **Git::Diff**: Diff operations
370
+ - Enumerable collection of `Git::Diff::DiffFile`
371
+ - Per-file patches and statistics
372
+ - Total insertion/deletion statistics
373
+
374
+ 7. **Git::Log**: Commit history query builder
375
+ - Chainable methods for building log queries
376
+ - Enumerable returning `Git::Object::Commit` objects
377
+ - Supports filtering by path, date range, author, etc.
378
+
379
+ ### Path Handling
380
+
381
+ ruby-git handles three types of paths:
382
+
383
+ - **Working directory paths**: Relative to repository working directory
384
+ - **Git directory paths**: The `.git` directory location
385
+ - **Object paths**: Paths within Git tree objects
386
+
387
+ The gem provides `Git::Path` and `Git::EscapedPath` for handling paths with special
388
+ characters.
389
+
390
+ ### Error Hierarchy
391
+
392
+ Proper error handling is essential for robust applications. The gem defines a
393
+ specific hierarchy of exception classes to allow callers to rescue specific failure
394
+ modes. All custom exceptions inherit from `Git::Error`:
395
+
396
+ - `Git::FailedError`: Git command exited with non-zero status
397
+ - `Git::SignaledError`: Git command was killed by a signal
398
+ - `Git::TimeoutError`: Git command exceeded timeout (subclass of SignaledError)
399
+ - `ArgumentError`: Invalid arguments passed to methods
400
+
401
+ All Git command errors include the command, output, and status for debugging.
402
+
403
+ ## Project Configuration
404
+
405
+ The following configuration values define the project's environment and operational
406
+ parameters. Use these settings to ensure your development environment matches the
407
+ project's requirements.
408
+
409
+ - **Language:** Ruby
410
+ - **Refactoring Strategy:** Maintain close alignment with git CLI commands, use
411
+ descriptive method names, avoid over-abstraction, favor Ruby idioms while keeping
412
+ git concepts clear
413
+
414
+ > **INSTRUCTIONS FOR AI:** Read these configuration values and use them strictly for
415
+ > the phases below. Do not guess commands.
416
+
417
+ - **Setup Project:** `bin/setup`
418
+ - **Run All Tests:** `bundle exec bin/test`
419
+ - **Run A Specific Test:** `bundle exec bin/test <test_file_name_without_extension>`
420
+ (e.g., `bundle exec bin/test test_branch`)
421
+ - **Run Linters:** `bundle exec rake rubocop yard`
422
+ - **Run Continuous Integration Workflow:** `bundle exec rake default`
423
+
424
+ ## Development Workflow
425
+
426
+ You are an expert and practical software engineer following a strict Test-Driven
427
+ Development (TDD) workflow.
428
+
429
+ **This project strictly follows Test Driven Development (TDD) practices. All
430
+ production code MUST be written using the TDD process described below.**
431
+
432
+ ### Workflow Overview
433
+
434
+ When assigned a task involving a GitHub issue, follow this workflow:
435
+
436
+ 1. **Phase 0: TRIAGE** - Understand the issue and determine if action is needed
437
+ 2. **Phase 1: PREPARE** - Set up the environment and plan the implementation
438
+ 3. **Phase 2: EXECUTE** - Implement the solution using TDD
439
+ 4. **Phase 3: FINALIZE** - Squash commits and create the PR
440
+
441
+ **Note:** Not all issues require implementation. Phase 0 may result in requesting
442
+ clarification, confirming the issue is a duplicate, or determining no changes are
443
+ needed.
444
+
445
+ ### Core TDD Principles
446
+
447
+ Adhere to the following fundamental principles to ensure high code quality and test
448
+ coverage:
449
+
450
+ - **Never Write Production Code without a Failing Test**
451
+ - **Bug Fixes Start with Tests:** Before fixing any bug, write a failing test that
452
+ demonstrates the bug and fails in the expected way. Only then fix the code to make
453
+ the test pass.
454
+ - **Tests Drive Design:** Let the test dictate the API and architecture. If the test
455
+ is hard to write, the design is likely wrong. When this happens, stop and suggest
456
+ one or more design alternatives. Offer to stash any current changes and work on the
457
+ design improvements first before continuing with the original task.
458
+ - **Write Tests Incrementally:** Build tests in small steps, writing just enough to
459
+ get the next expected failure. For example, first write a test that references a
460
+ class that doesn't exist (fails), then define the empty class (passes), then extend
461
+ the test to call a method (fails), then define the method (passes), etc.
462
+ - **Tests Should Be Atomic:** Each test should verify exactly one logical behavior,
463
+ making failures easy to diagnose and understand.
464
+ - **Prefer the Simplest Solution:** Choose the simplest implementation that could
465
+ possibly work, even if it seems naive. Complexity should only be added when driven
466
+ by actual requirements in tests.
467
+ - **No Implementation in Advance:** Only write the code strictly needed to pass the
468
+ current test.
469
+
470
+ ### Phase 0: TRIAGE
471
+
472
+ The purpose of this phase is to understand what the issue is asking for, investigate
473
+ the current state of the codebase, and determine whether implementation is needed.
474
+
475
+ **Use this phase when the user references a GitHub issue number** (e.g., "Fix issue
476
+ \#999", "Implement \#999", "Diagnose issue \#999").
477
+
478
+ 1. **Fetch the Issue:** Use `gh issue view #999` to read the full issue content,
479
+ including description, comments, and labels.
480
+
481
+ 2. **Understand the Request:** Analyze what is being asked:
482
+ - Is this a bug report? Feature request? Question? Documentation issue?
483
+ - Is the issue clear and actionable, or does it need clarification?
484
+ - Are there reproduction steps or examples provided?
485
+
486
+ 3. **Search for Context:** Investigate the codebase to understand the area affected:
487
+ - Use `grep_search` or `semantic_search` to find relevant code
488
+ - Read related test files to understand existing behavior
489
+ - Check if similar functionality already exists
490
+ - Look for related issues or PRs that might be relevant
491
+
492
+ 4. **Reproduce (if applicable):** For bug reports:
493
+ - Try to reproduce the issue based on the provided steps
494
+ - Run existing tests to see if they catch the issue
495
+ - Verify the issue still exists in the current codebase
496
+
497
+ 5. **Determine Next Steps and Report Findings:**
498
+
499
+ **Option A: Issue needs clarification**
500
+ - Comment on the issue using `gh issue comment #999 --body "..."`
501
+ - Ask specific questions about reproduction steps, expected behavior, or use case
502
+ - **STOP here** - wait for user/reporter response before proceeding
503
+
504
+ **Option B: Issue is not actionable (duplicate, won't-fix, already resolved)**
505
+ - Comment on the issue explaining your findings
506
+ - Suggest closing the issue or linking to related issues
507
+ - **STOP here** - no implementation needed
508
+
509
+ **Option C: Issue is clear and actionable**
510
+ - Comment on the issue confirming you understand the request and plan to implement
511
+ - Summarize your understanding and proposed approach
512
+ - **Proceed to Phase 1: PREPARE** to begin implementation
513
+
514
+ **Option D: User asked only to diagnose (not implement)**
515
+ - Comment on the issue with your diagnostic findings
516
+ - Explain what you discovered (root cause, affected code, potential solutions)
517
+ - **STOP here** - wait for confirmation to proceed with implementation
518
+
519
+ **GitHub CLI Commands for Phase 0:**
520
+
521
+ - View issue: `gh issue view #999`
522
+ - View with comments: `gh issue view #999 --comments`
523
+ - Comment on issue: `gh issue comment #999 --body "Your comment here"`
524
+ - Search issues: `gh issue list --search "keyword"`
525
+
526
+ ### Phase 1: PREPARE
527
+
528
+ The purpose of this phase is to ensure the project environment is ready, establish a
529
+ clean baseline, and create a clear implementation plan before writing any code.
530
+
531
+ **Only proceed to this phase if Phase 0 determined that implementation is needed.**
532
+
533
+ 1. **Check Uncommitted Changes:** If there are any uncommitted changes in the
534
+ project, ask the user what to do with them before continuing: include them in the
535
+ current implementation plan, ignore them, or stash them before continuing.
536
+ 2. **Create Feature Branch:** Create a new branch from `origin/main` using the naming
537
+ convention `<type>/<short-description>` (e.g., `fix/issue-999`).
538
+ 3. **Verify Project Setup:** Run the `Setup Project` command to ensure that the
539
+ project is ready for development.
540
+ 4. **Verify Clean Baseline:** Ensure that all existing tests and linters pass by
541
+ running the `Run Continuous Integration Workflow` command.
542
+ 5. **Analyze and Plan:** Understand the requirements, identify edge cases and
543
+ potential challenges, and break the work into small, isolated tasks. Consider what
544
+ tests will be needed and in what order they should be written.
545
+ 6. **Consider Refactoring:** Look for ways to make the implementation of the feature
546
+ or bug fix easier by performing one or more refactorings. If any are found,
547
+ suggest them to the user. If the user confirms the refactoring, do the refactoring
548
+ in a separate TDD process. Only once the refactoring is completed should the
549
+ current feature or bug fix be worked on.
550
+
551
+ ### Phase 2: EXECUTE
552
+
553
+ The purpose of this phase is to implement each planned task using strict TDD cycles,
554
+ ensuring every line of production code is driven by a failing test.
555
+
556
+ Execute each task by repeating the following cycle of steps until all tasks are
557
+ complete:
558
+
559
+ 1. **RED-GREEN:** Write failing tests and implement code to make them pass
560
+ 2. **REFACTOR:** Improve code quality and design without changing behavior
561
+ 3. **VERIFY:** Confirm the task is complete and code meets quality standards
562
+ 4. **COMMIT:** Create a commit for the completed task
563
+ 5. **REPLAN:** Review the implementation plan, then return to step 1 for the next
564
+ task
565
+
566
+ When all tasks are complete, proceed to [Phase 3: FINALIZE](#phase-3-finalize).
567
+
568
+ #### RED-GREEN Step
569
+
570
+ 1. **RED Substep**
571
+
572
+ The purpose of this substep is to write a failing test that you hypothesize will
573
+ pass with the next incremental bit of task implementation.
574
+
575
+ - **Write the Test:** Write a single, focused, failing test or extend an existing
576
+ test for the current task.
577
+ - **Keep It Minimal:** Only write enough of a test to get an expected, failing
578
+ result (the test should fail for the *right* reason).
579
+ - **Execute and Analyze:** Run the `Run A Specific Test` command and analyze the
580
+ output.
581
+ - **Confirm Expected Failure:** Confirm it fails with an expected error (e.g.,
582
+ assertion failure or missing definition).
583
+ - **Validate:** If the test passes without implementation, the test is invalid or
584
+ the logic already exists. When that happens, revise or skip.
585
+
586
+ 2. **GREEN Substep**
587
+
588
+ The purpose of this substep is to write just enough production code to make the
589
+ failing test(s) pass.
590
+
591
+ - **Write Minimal Code:** Write the minimum amount of code required to make the
592
+ test pass.
593
+ - **Use Simple Solutions:** It is acceptable to use hardcoded values or "quick and
594
+ dirty" logic here just to get to green, even if this means intentionally writing
595
+ clearly suboptimal code that you will improve during the REFACTOR step.
596
+ - **No Premature Optimization:** Do NOT optimize, clean up, or improve code style
597
+ during GREEN—that work belongs in the REFACTOR step.
598
+ - **Execute and Verify:** Run the `Run A Specific Test` command
599
+ - **If the test passes**, proceed to the REFACTOR step
600
+ - **If the test fails**, read the FULL error output including the stack trace.
601
+ Identify the exact failing line and assertion before modifying any code. Fix
602
+ only what the error indicates, then re-run. Repeat until the test passes.
603
+ - **Rollback on Repeated Failure:** If the test cannot be made to pass within 3
604
+ attempts, revert all changes from this RED-GREEN cycle, report the issue to the
605
+ user, and ask for guidance before proceeding.
606
+ - **Stay Focused:** Do not implement future features or optimizations yet.
607
+
608
+ #### REFACTOR Step
609
+
610
+ The purpose of this step is to improve code quality and design without changing
611
+ behavior, ensuring the codebase remains clean and maintainable.
612
+
613
+ **You must consider refactoring before starting the next task.** Remove duplication,
614
+ improve variable names, and apply design patterns. Skip this step only if the code is
615
+ already clean and simple—avoid over-engineering.
616
+
617
+ - **Generalize the Implementation:** Ensure the code solves the general case, not
618
+ just the specific test case. Replace hardcoded values used to pass the test with
619
+ actual logic.
620
+ - **Limit Scope:** Do not perform refactorings that affect files outside the
621
+ immediate scope of the current task. If a broader refactor is needed, add it to the
622
+ task list during the REPLAN step as a separate task.
623
+ - **Execute All Tests:** Run the `Run All Tests` command and verify they still pass.
624
+ - **Verify Test Independence:** Verify tests can run independently in any order.
625
+ - **Confirm Improvement:** Ensure the refactoring made the code clearer, simpler, or
626
+ more maintainable.
627
+
628
+ #### VERIFY Step
629
+
630
+ The purpose of this step is to confirm that the current task is fully complete before
631
+ moving to the next task.
632
+
633
+ - **Confirm Implementation Complete:** Verify all functionality for the task is
634
+ implemented.
635
+ - **Run All Tests:** Run the `Run All Tests` command to ensure all tests pass.
636
+ - **Run Linters:** Run the `Run Linters` command to verify code style and
637
+ documentation standards.
638
+ - **Check Code Quality:** Confirm the code is clean and well-factored.
639
+ - **STOP on Unexpected Failure:** If any test unexpectedly fails during VERIFY, STOP
640
+ immediately and report the failure to the user. Do not attempt to fix the failure
641
+ without first explaining what went wrong and getting confirmation to proceed.
642
+
643
+ #### COMMIT Step
644
+
645
+ The purpose of this step is to create a checkpoint after successfully completing a
646
+ task, providing a safe rollback point.
647
+
648
+ - **Create Commit:** Commit all changes from this task using the appropriate
649
+ conventional commit type (see [Per-Task Commits](#per-task-commits) for guidance).
650
+ - **Keep Commits Atomic:** Each commit should represent one completed task with all
651
+ tests passing and linters clean.
652
+
653
+ #### REPLAN Step
654
+
655
+ The purpose of this step is to review progress and adjust the implementation plan
656
+ based on what was learned during the current task.
657
+
658
+ - **Review Implementation Plan:** Assess whether the remaining tasks are still valid
659
+ and appropriately scoped based on what was learned.
660
+ - **Identify New Tasks:** If the implementation revealed new requirements, edge
661
+ cases, or necessary refactorings, add them to the task list.
662
+ - **Reprioritize if Needed:** Adjust task order if dependencies or priorities have
663
+ changed.
664
+ - **Report Progress:** Briefly summarize what was completed and what remains.
665
+ **ALWAYS** print the updated task list with status (e.g., `[x] Task 1`, `[ ] Task
666
+ 2`).
667
+ - **Continue or Complete:** If tasks remain, return to RED-GREEN for the next task.
668
+ If all tasks are complete, proceed to [Phase 3: FINALIZE](#phase-3-finalize).
669
+
670
+ ### Phase 3: FINALIZE
671
+
672
+ The purpose of this phase is to consolidate all task commits into a single, clean
673
+ commit and complete the feature or bug fix.
674
+
675
+ 1. **Run Final Verification:** Run the `Run Continuous Integration Workflow` command
676
+ one final time to ensure everything passes.
677
+ 2. **Safety Check:** Run `git log --oneline HEAD~N..HEAD` (where N is the number of
678
+ task commits) to list the commits included in the squash. Verify these are
679
+ strictly the commits generated during the current session. If unexpected commits
680
+ appear, STOP and ask the user for the correct value of N.
681
+ 3. **Capture Commit Messages:** Run `git log --format="- %s" HEAD~N..HEAD` to capture
682
+ individual commit messages for inclusion in the final commit body.
683
+ 4. **Draft the Squash Message:** Prepare a commit message with:
684
+ - **Subject:** A single line summarizing the entire feature or fix (e.g.,
685
+ `feat(branch): add Branch#create method`)
686
+ - **Body:** A summary of what was implemented, the captured commit messages from
687
+ step 2, key decisions made, and any relevant context. Wrap lines at 100
688
+ characters.
689
+ 5. **Propose the Squash:** Present the drafted message and the commands to squash to
690
+ the user:
691
+ - `git reset --soft HEAD~N` (where N is the number of task commits)
692
+ - `git commit -m "<drafted message>"`
693
+ 6. **Wait for Confirmation:** Do NOT execute the squash until the user reviews the
694
+ commits and confirms. The user may want to adjust the message or keep some commits
695
+ separate.
696
+ 7. **Execute on Confirmation:** Once confirmed, run `git reset --soft HEAD~N` to
697
+ unstage the task commits while preserving all changes, then commit with the
698
+ approved message.
699
+ 8. **Handle Commit Hook Failure:** If the commit fails due to a `commit-msg` hook
700
+ rejection (e.g., commitlint error):
701
+ - Read the error message carefully to identify the formatting issue.
702
+ - Fix the commit message to comply with the project's commit conventions.
703
+ - Retry the commit. The changes remain staged after a hook failure, so only the
704
+ `git commit` command needs to be re-run.
705
+ - If the commit fails 3 times, STOP and report the issue to the user with the
706
+ exact error message.
707
+
708
+ ## Pull Request Review Workflow
709
+
710
+ When asked to review a pull request (e.g., "Review PR #999"), follow this workflow to
711
+ analyze the changes, provide feedback, and optionally post the review to GitHub.
712
+
713
+ ### Step 1: Fetch the PR
714
+
715
+ 1. **Read PR Details:** Use `gh pr view #999` to get title, description, author, and
716
+ status.
717
+ 2. **Get Changed Files:** Use `gh pr diff #999` to see the complete diff.
718
+ 3. **Check PR Status:** Note if it's a draft, has merge conflicts, or has existing
719
+ reviews.
720
+
721
+ ### Step 2: Review Against Project Standards
722
+
723
+ Evaluate the PR against these criteria:
724
+
725
+ **Code Quality:** Ruby style (Rubocop-compliant), `frozen_string_literal: true`, proper naming (snake_case/PascalCase), single-responsibility, no duplication, Ruby 3.2+ idioms.
726
+
727
+ **Testing:** Changes covered by atomic Test::Unit tests, well-named, passing CI. Test modifications require justification.
728
+
729
+ **Documentation:** YARD docs on public methods with `@param`, `@return`, `@raise`, `@example`. README updated for user-facing changes. Platform differences and security documented.
730
+
731
+ **Architecture:** Correct layer placement (Base/Lib/CommandLine), principle of least surprise, direct Git command mapping, proper error hierarchy.
732
+
733
+ **Commits:** Conventional Commits format, lowercase subjects under 100 chars, no trailing period. Breaking changes use `!` and `BREAKING CHANGE:` footer.
734
+
735
+ **Compatibility:** Backward compatible (or marked breaking), Ruby 3.2+, Git 2.28.0+, cross-platform (Windows/macOS/Linux).
736
+
737
+ **Security:** No command injection, proper escaping via Git::CommandLine, input validation, resource cleanup.
738
+
739
+ ### Step 3: Present Review Findings
740
+
741
+ Present your findings to the user in this format:
742
+
743
+ ```text
744
+ ## PR Review: #999 - [PR Title]
745
+
746
+ **Author:** [username]
747
+ **Status:** [open/draft/has conflicts/etc.]
748
+
749
+ ### Summary
750
+ [Brief description of what the PR does]
751
+
752
+ ### Recommendation
753
+ - **Review Type:** [APPROVE / COMMENT / REQUEST CHANGES]
754
+ - **Rationale:** [Why this recommendation]
755
+
756
+ ### General Comments
757
+
758
+ [Overall feedback on the PR - architecture decisions, approach, etc.]
759
+
760
+ ### Line-Specific Comments
761
+
762
+ [file.rb:123]
763
+ [Specific feedback about this line or section]
764
+
765
+ [file.rb:456-460]
766
+ [Feedback about this range of lines]
767
+
768
+ ### Checklist Results
769
+
770
+ **Passing:**
771
+ - Uses proper Ruby style
772
+ - Tests included
773
+ - ...
774
+
775
+ **Issues Found:**
776
+ - Missing YARD documentation on `SomeClass#method`
777
+ - Commit message "Fixed bug" doesn't follow conventional commits
778
+ - ...
779
+
780
+ ---
781
+
782
+ **Here is the review. Do you have any questions or want additional changes, OR should I go ahead and post this review on the PR?**
783
+ ```
784
+
785
+ ### Step 4: Get User Approval
786
+
787
+ Wait for the user to respond. They may:
788
+
789
+ - **Approve posting:** Proceed to Step 5
790
+ - **Request changes to review:** Modify your findings and re-present
791
+ - **Ask questions:** Answer and clarify before proceeding
792
+ - **Decide not to post:** End the workflow
793
+
794
+ Do NOT post the review without explicit user confirmation.
795
+
796
+ ### Step 5: Post the Review
797
+
798
+ Once the user confirms, post the review using the GitHub CLI:
799
+
800
+ **For reviews with line-specific comments:**
801
+
802
+ 1. Create the review: `gh pr review #999 --comment` (or `--approve` or
803
+ `--request-changes`)
804
+ 2. Add the general comment as the review body using `-b "comment text"`
805
+ 3. For line-specific comments, you may need to use the GitHub API or instruct the
806
+ user to add them manually in the GitHub UI
807
+
808
+ **For reviews with only general comments:**
809
+
810
+ ```bash
811
+ gh pr review #999 --approve -b "Your general comment here"
812
+ # or
813
+ gh pr review #999 --comment -b "Your general comment here"
814
+ # or
815
+ gh pr review #999 --request-changes -b "Your general comment here"
816
+ ```
817
+
818
+ **Note:** The `gh` CLI has limitations with line-specific comments. If the review
819
+ includes line-specific comments, inform the user of this limitation and either:
820
+
821
+ - Post only the general comment via CLI and provide the line comments for manual
822
+ posting
823
+ - Provide the full review text for the user to post manually
824
+ - Use the GitHub API if line-specific commenting is critical
825
+
826
+ ### Step 6: Confirm Completion
827
+
828
+ After posting, confirm with the user:
829
+
830
+ ```text
831
+ Review posted successfully to PR #999.
832
+ View at: [PR URL from gh pr view output]
833
+ ```
834
+
835
+ ## CI/CD Troubleshooting Workflow
836
+
837
+ When asked to diagnose or fix CI/CD failures (e.g., "Why is CI failing on PR #999?",
838
+ "Fix the failing build"), follow this workflow to identify the root cause and
839
+ optionally implement fixes.
840
+
841
+ ### Step 1: Identify the Failure
842
+
843
+ 1. **Get CI Status:**
844
+ - For PRs: `gh pr checks #999`
845
+ - For branches: `gh run list --branch <branch-name> --limit 5`
846
+ - Note which jobs passed and which failed
847
+
848
+ 2. **Categorize the Failure Type:**
849
+ - **Test failures** - Unit tests, integration tests failing
850
+ - **Linter failures** - Rubocop, YARD documentation issues
851
+ - **Build failures** - Dependency installation, compilation errors
852
+ - **Timeout failures** - Jobs exceeding time limits
853
+ - **Platform-specific failures** - Failing on specific Ruby version or OS
854
+
855
+ 3. **Identify Specific Failing Steps:**
856
+ - Note the exact job name and step that failed
857
+ - Record the Ruby version, OS, and other environment details
858
+
859
+ ### Step 2: Fetch Relevant Logs
860
+
861
+ **CRITICAL: CI logs can be massive (100K+ lines) and exceed token limits.**
862
+
863
+ 1. **Get the Run ID:**
864
+
865
+ ```bash
866
+ gh run list --branch <branch> --limit 1 --json databaseId --jq '.[0].databaseId'
867
+ ```
868
+
869
+ 2. **Fetch Failed Job Logs Only:**
870
+
871
+ ```bash
872
+ gh run view <run-id> --log-failed
873
+ ```
874
+
875
+ This limits output to only failed jobs, making it manageable.
876
+
877
+ 3. **Extract Key Error Information:**
878
+
879
+ - For test failures: Look for stack traces, assertion errors, specific test names
880
+ - For linter failures: Extract file names, line numbers, and violation types
881
+ - For build failures: Find dependency errors or missing packages
882
+ - Use `grep` to filter logs if still too large:
883
+
884
+ ```bash
885
+ gh run view <run-id> --log-failed | grep -A 10 -B 5 "Error\|FAILED\|Failure"
886
+ ```
887
+
888
+ 4. **Avoid Full Log Downloads:**
889
+
890
+ - Do NOT use `--log` without `--log-failed` unless specifically requested
891
+ - If logs are still too large, focus on the most recent or critical failure
892
+
893
+ ### Step 3: Diagnose Root Cause
894
+
895
+ Based on the failure type, investigate:
896
+
897
+ **For Test Failures:**
898
+
899
+ - Check if the test exists and what it's testing
900
+ - Look for recent changes that might have broken the test
901
+ - Consider environment differences (local vs. CI)
902
+ - Check for flaky tests (intermittent failures)
903
+
904
+ **For Linter Failures:**
905
+
906
+ - Run linters locally: `bundle exec rake rubocop yard`
907
+ - Identify specific violations from the log
908
+ - Check if violations are in files related to recent changes
909
+
910
+ **For Build Failures:**
911
+
912
+ - Check dependency versions in `Gemfile` and `git.gemspec`
913
+ - Look for platform-specific dependency issues
914
+ - Verify Ruby version compatibility
915
+
916
+ **For Timeout Failures:**
917
+
918
+ - Identify which test or step is timing out
919
+ - Check for infinite loops or performance regressions
920
+ - Consider if it's a resource limitation in CI environment
921
+
922
+ ### Step 4: Reproduce Locally (if applicable)
923
+
924
+ **For PR Failures:**
925
+
926
+ 1. Fetch the PR branch:
927
+
928
+ ```bash
929
+ gh pr checkout #999
930
+ ```
931
+
932
+ 2. Run the failing tests locally:
933
+
934
+ ```bash
935
+ bundle exec bin/test <test-name>
936
+ ```
937
+
938
+ 3. Run linters:
939
+
940
+ ```bash
941
+ bundle exec rake rubocop yard
942
+ ```
943
+
944
+ **For Branch Failures:**
945
+
946
+ 1. Checkout the branch.
947
+ 2. Run full CI workflow:
948
+
949
+ ```bash
950
+ bundle exec rake default
951
+ ```
952
+
953
+ ### Step 5: Report Findings or Fix
954
+
955
+ Determine the appropriate action based on the user's request:
956
+
957
+ #### Option A: Diagnostic Report ("Why is CI failing?")
958
+
959
+ Present findings to the user:
960
+
961
+ ````markdown
962
+ ## CI Failure Diagnosis: <Branch/PR>
963
+
964
+ **Status:** <X of Y jobs failed>
965
+
966
+ ### Failed Jobs
967
+ 1. **<Job Name>** (<Ruby version>, <OS>)
968
+ - **Step:** <failing step name>
969
+ - **Failure Type:** <test/linter/build/timeout>
970
+
971
+ ### Root Cause
972
+ <Explanation of what's causing the failure>
973
+
974
+ ### Error Details
975
+ ```
976
+ <Relevant error messages and stack traces>
977
+ ```
978
+
979
+ ### Recommendations
980
+ - <Specific fix suggestion 1>
981
+ - <Specific fix suggestion 2>
982
+
983
+ **Would you like me to implement a fix, or do you need more information?**
984
+ ````
985
+
986
+ **STOP here** unless the user asks you to proceed with fixes.
987
+
988
+ #### Option B: Implement Fix ("Fix the failing build")
989
+
990
+ Proceed based on failure type:
991
+
992
+ - **Test Failures:** Use the full TDD workflow (Phase 1-3) to fix the failing tests
993
+ - **Linter Failures:** Fix violations directly, commit with appropriate message
994
+ (e.g., `style: fix rubocop violations in lib/git/base.rb`)
995
+ - **Build Failures:** Update dependencies or configuration as needed
996
+ - **Timeout Failures:** Investigate performance issues, may require user guidance
997
+
998
+ **For PR Failures on Someone Else's PR:**
999
+
1000
+ - You may not have push access to their branch
1001
+ - Present the fix and ask user to either:
1002
+ - Push to the PR branch (if they have access)
1003
+ - Comment on the PR with suggested changes
1004
+ - Create a new PR with fixes
1005
+
1006
+ ### Step 6: Verify Fix
1007
+
1008
+ After implementing fixes:
1009
+
1010
+ 1. **Run Affected Tests Locally:**
1011
+
1012
+ ```bash
1013
+ bundle exec bin/test <test-name>
1014
+ ```
1015
+
1016
+ 2. **Run Full CI Suite:**
1017
+
1018
+ ```bash
1019
+ bundle exec rake default
1020
+ ```
1021
+
1022
+ 3. **Push and Monitor:**
1023
+
1024
+ - Push the fixes
1025
+ - Monitor CI to confirm the fix worked:
1026
+
1027
+ ```bash
1028
+ gh run watch
1029
+ ```
1030
+
1031
+ 4. **Confirm Resolution:**
1032
+
1033
+ ```text
1034
+ Fix implemented and pushed. Monitoring CI run...
1035
+ CI Status: <link to run>
1036
+ ```
1037
+
1038
+ ### Special Troubleshooting Considerations
1039
+
1040
+ **Platform-Specific Failures:**
1041
+
1042
+ - If tests pass on macOS but fail on Linux/Windows, document the difference
1043
+ - Check for path separator issues (`/` vs. `\`)
1044
+ - Look for encoding differences
1045
+ - Consider file system case sensitivity
1046
+
1047
+ **Flaky Tests:**
1048
+
1049
+ - If a test fails intermittently, note this in your diagnosis
1050
+ - Run the test multiple times locally to confirm flakiness
1051
+ - Suggest fixes for race conditions or timing issues
1052
+
1053
+ **Permission Issues:**
1054
+
1055
+ - If you can't push to a PR branch, clearly communicate this limitation
1056
+ - Provide the exact commands or changes needed for the user to apply
1057
+
1058
+ **Token Limit Management:**
1059
+
1060
+ - Always use `--log-failed` to limit output
1061
+ - If logs are still too large, use `grep` to extract errors
1062
+ - Focus on the first failure if multiple failures exist
1063
+ - Consider running tests locally instead of relying on full CI logs
1064
+
1065
+ ## Test Debugging & Maintenance Workflow
1066
+
1067
+ When asked to debug tests or improve test coverage (e.g., "Why is test_branch
1068
+ failing?", "Fix flaky test", "Improve test coverage"), follow this workflow to
1069
+ identify problems, determine root causes, and apply appropriate fixes.
1070
+
1071
+ ### Understanding Test Failure Types
1072
+
1073
+ **Consistent Failures:**
1074
+
1075
+ - Test fails every time it runs
1076
+ - Usually indicates a real bug or broken test
1077
+ - Easier to debug than flaky tests
1078
+
1079
+ **Flaky/Intermittent Failures:**
1080
+
1081
+ - Test passes sometimes, fails other times
1082
+ - Often indicates:
1083
+ - Race conditions
1084
+ - Timing dependencies
1085
+ - Shared state between tests
1086
+ - Non-deterministic behavior (random data, time-based logic)
1087
+ - External dependencies (filesystem, network)
1088
+ - Test execution order dependencies
1089
+
1090
+ **Test Coverage Gaps:**
1091
+
1092
+ - Existing code lacks sufficient test coverage
1093
+ - Not a failure, but maintenance task
1094
+ - Use TDD workflow to add tests
1095
+
1096
+ ### Step 1: Run and Observe the Test
1097
+
1098
+ 1. **Run the Failing Test:**
1099
+
1100
+ ```bash
1101
+ bundle exec bin/test <test_file_name>
1102
+ ```
1103
+
1104
+ Capture the full output including stack trace.
1105
+
1106
+ 2. **Run Specific Test Method (if needed):**
1107
+
1108
+ ```bash
1109
+ bundle exec ruby -I lib:tests tests/units/test_base.rb -n test_method_name
1110
+ ```
1111
+
1112
+ 3. **For Suspected Flaky Tests, Run Multiple Times:**
1113
+
1114
+ ```bash
1115
+ # Run 20 times, stop on first failure
1116
+ for i in {1..20}; do
1117
+ echo "Run $i"
1118
+ bundle exec bin/test test_branch || break
1119
+ done
1120
+ ```
1121
+
1122
+ If it fails inconsistently, it's flaky.
1123
+
1124
+ 4. **Check Test Isolation:**
1125
+
1126
+ ```bash
1127
+ # Run test file in isolation
1128
+ bundle exec bin/test test_branch
1129
+
1130
+ # Run full suite to see if other tests affect it
1131
+ bundle exec bin/test
1132
+ ```
1133
+
1134
+ ### Step 2: Understand the Test
1135
+
1136
+ 1. **Read the Test Code:**
1137
+
1138
+ - What behavior is being tested?
1139
+ - What is the expected outcome?
1140
+ - What setup/teardown occurs?
1141
+ - Are there any mocks or stubs?
1142
+
1143
+ 2. **Understand the Error:**
1144
+
1145
+ - Read the full error message and stack trace
1146
+ - Identify the exact line that failed
1147
+ - Understand expected vs. actual values
1148
+ - Check if it's an assertion failure or exception
1149
+
1150
+ 3. **Review Related Tests:**
1151
+
1152
+ - Do similar tests pass?
1153
+ - Are there patterns in what works vs. what doesn't?
1154
+
1155
+ ### Step 3: Investigate Root Cause
1156
+
1157
+ **For Consistent Failures:**
1158
+
1159
+ 1. **Check Recent Changes:**
1160
+
1161
+ - Use `git log` to see recent commits to test file or related production code
1162
+ - Use `git blame` on the failing test to see when it was last modified
1163
+
1164
+ 2. **Look for Broken Assumptions:**
1165
+
1166
+ - Has the API changed?
1167
+ - Are test fixtures or data still valid?
1168
+ - Are external dependencies (git version, Ruby version) compatible?
1169
+
1170
+ 3. **Check Test Setup/Teardown:**
1171
+
1172
+ - Is setup creating the necessary preconditions?
1173
+ - Is teardown cleaning up properly?
1174
+ - Use test helpers (`clone_working_repo`, `create_temp_repo`, etc.)
1175
+
1176
+ 4. **Environment Issues:**
1177
+
1178
+ - Platform differences (paths, line endings, permissions)
1179
+ - Missing dependencies or configuration
1180
+ - Git configuration on the system
1181
+
1182
+ **For Flaky Tests:**
1183
+
1184
+ 1. **Look for Race Conditions:**
1185
+
1186
+ - Multiple threads or processes
1187
+ - File system operations without proper synchronization
1188
+ - Async operations without proper waiting
1189
+
1190
+ 2. **Check for Timing Dependencies:**
1191
+
1192
+ - Tests that depend on execution speed
1193
+ - Sleep statements or timeouts
1194
+ - Time-based logic (dates, timestamps)
1195
+
1196
+ 3. **Identify Shared State:**
1197
+
1198
+ - Global variables or class variables
1199
+ - Shared file system resources
1200
+ - Tests affecting each other through side effects
1201
+
1202
+ 4. **Look for Non-Determinism:**
1203
+
1204
+ - Random data generation
1205
+ - Hash ordering (though Ruby 1.9+ maintains insertion order)
1206
+ - Iteration over sets without guaranteed order
1207
+ - Time-dependent logic (Time.now, Date.today)
1208
+
1209
+ 5. **Check Test Execution Order:**
1210
+
1211
+ - Does the test only pass when run after certain other tests?
1212
+ - Does it fail when run in isolation?
1213
+ - Use `--seed` option to reproduce specific execution order
1214
+
1215
+ ### Step 4: Report Findings
1216
+
1217
+ Present your diagnostic findings to the user:
1218
+
1219
+ ````markdown
1220
+ ## Test Failure Diagnosis: <test_name>
1221
+
1222
+ **Failure Type:** [Consistent / Flaky / Coverage Gap]
1223
+ **Test File:** <path/to/test_file.rb>
1224
+ **Test Method:** <test_method_name>
1225
+
1226
+ ### Error
1227
+ ```
1228
+ <error message and relevant stack trace>
1229
+ ```
1230
+
1231
+ ### Root Cause
1232
+ <Explanation of why the test is failing>
1233
+
1234
+ ### Affected Code
1235
+ - Test code: <relevant test code>
1236
+ - Production code: <relevant production code if applicable>
1237
+
1238
+ ### Recommended Fix
1239
+ <Specific recommendation based on scenario below>
1240
+
1241
+ **Would you like me to implement this fix?**
1242
+ ````
1243
+
1244
+ **STOP here** unless the user asks you to proceed with the fix.
1245
+
1246
+ ### Step 5: Determine Fix Strategy and Execute
1247
+
1248
+ Based on the root cause, choose the appropriate fix strategy:
1249
+
1250
+ #### Scenario A: Production Code Bug (Test Caught a Real Bug)
1251
+
1252
+ - **Strategy:** Fix production code using TDD workflow
1253
+ - **Process:**
1254
+ 1. The failing test already exists (RED step done)
1255
+ 2. **Proceed to Phase 1: PREPARE** of the TDD workflow
1256
+ 3. Fix the production code (GREEN step)
1257
+ 4. Refactor if needed
1258
+ 5. Continue through Phase 2-3 as normal
1259
+ - **Commit:** `fix(component): <description>` with test changes if needed
1260
+
1261
+ #### Scenario B: Test Needs Updating (Intentional API Change)
1262
+
1263
+ - **Strategy:** Update test to match new expected behavior
1264
+ - **CRITICAL:** Get user confirmation before modifying test!
1265
+ - **Process:**
1266
+ 1. Explain what changed and why test expectations are now different
1267
+ 2. Ask if this is a breaking change
1268
+ 3. Wait for user approval
1269
+ 4. Update test assertions or setup
1270
+ 5. Verify test passes
1271
+ 6. Run full test suite
1272
+ - **Commit:** `test(component): update test for <change>`
1273
+
1274
+ #### Scenario C: Flaky Test (Non-Determinism)
1275
+
1276
+ - **Strategy:** Make test deterministic
1277
+ - **Process:**
1278
+ 1. Identify source of non-determinism
1279
+ 2. Fix the test to be deterministic:
1280
+ - Stub time-dependent code (freeze time in tests)
1281
+ - Use fixed seed for random data
1282
+ - Add proper synchronization for async operations
1283
+ - Isolate tests from each other (proper setup/teardown)
1284
+ - Remove timing dependencies
1285
+ 3. Run test 20+ times to verify fix
1286
+ 4. Run full test suite
1287
+ - **Commit:** `test(component): fix flaky test in <test_name>`
1288
+ - **If production code has race condition:** Also fix that using TDD workflow
1289
+
1290
+ #### Scenario D: Missing Test Coverage
1291
+
1292
+ - **Strategy:** Add tests using TDD workflow
1293
+ - **Process:**
1294
+ 1. **Proceed to Phase 1: PREPARE** of the TDD workflow
1295
+ 2. Write tests for uncovered code (RED step)
1296
+ 3. If tests pass → good! Code works, test documents behavior
1297
+ 4. If tests fail → found a bug, proceed with GREEN step
1298
+ 5. Continue through normal TDD cycle
1299
+ - **Commit:** `test(component): add tests for <feature>`
1300
+
1301
+ #### Scenario E: Test Refactoring/Cleanup
1302
+
1303
+ - **Strategy:** Improve test quality without changing behavior
1304
+ - **Process:**
1305
+ 1. Keep test green while refactoring
1306
+ 2. Improve readability, reduce duplication
1307
+ 3. Extract test helpers if needed
1308
+ 4. Run test after each change to ensure still passing
1309
+ 5. Run full test suite
1310
+ - **Commit:** `refactor(test): improve test clarity in <test_name>`
1311
+
1312
+ #### Scenario F: Environment/Setup Issue
1313
+
1314
+ - **Strategy:** Fix environment, not code
1315
+ - **Process:**
1316
+ 1. Document the environment requirement
1317
+ 2. Update README or test setup if needed
1318
+ 3. May need to run `bin/setup` or install dependencies
1319
+ 4. No code commit needed unless documenting requirement
1320
+
1321
+ ### Step 6: Verify Test Fix
1322
+
1323
+ After implementing the fix:
1324
+
1325
+ 1. **Run the Specific Test:**
1326
+
1327
+ ```bash
1328
+ bundle exec bin/test <test_file>
1329
+ ```
1330
+
1331
+ 2. **For Flaky Test Fixes, Run Many Times:**
1332
+
1333
+ ```bash
1334
+ for i in {1..50}; do
1335
+ echo "Run $i"
1336
+ bundle exec bin/test test_branch || break
1337
+ done
1338
+ ```
1339
+
1340
+ Should pass all 50 times.
1341
+
1342
+ 3. **Verify Test Isolation:**
1343
+
1344
+ ```bash
1345
+ # Run test alone
1346
+ bundle exec ruby -I lib:tests tests/units/test_base.rb -n test_method
1347
+
1348
+ # Run full suite
1349
+ bundle exec bin/test
1350
+ ```
1351
+
1352
+ 4. **Run Full Test Suite:**
1353
+
1354
+ ```bash
1355
+ bundle exec rake default
1356
+ ```
1357
+
1358
+ 5. **Confirm Fix:**
1359
+
1360
+ ```text
1361
+ Test fix verified:
1362
+ - Test passes consistently (ran 50 times for flaky test)
1363
+ - Test passes in isolation
1364
+ - Full test suite passes
1365
+ - No regressions introduced
1366
+ ```
1367
+
1368
+ ### Special Considerations
1369
+
1370
+ **Test Isolation:**
1371
+
1372
+ - Each test should be independent
1373
+ - Setup should create fresh state
1374
+ - Teardown should clean up completely
1375
+ - Use `clone_working_repo` or `create_temp_repo` from test helpers
1376
+ - Don't rely on test execution order
1377
+
1378
+ **Platform-Specific Tests:**
1379
+
1380
+ - Some tests may behave differently on Windows vs. Unix
1381
+ - Check for path separator issues (`/` vs. `\\`)
1382
+ - File permissions work differently across platforms
1383
+ - Line endings (CRLF vs. LF) can affect tests
1384
+
1385
+ **CI vs. Local:**
1386
+
1387
+ - CI may have different environment (different Ruby version, Git version, OS)
1388
+ - CI runs tests in different order
1389
+ - CI may have stricter resource limits
1390
+ - Use CI/CD Troubleshooting Workflow if failing only in CI
1391
+
1392
+ **Test Data Management:**
1393
+
1394
+ - Test fixtures are in `tests/files/`
1395
+ - Use test helpers to create temporary repos
1396
+ - Clean up temporary files in teardown
1397
+ - Don't commit generated test data
1398
+
1399
+ **Mocking and Stubbing:**
1400
+
1401
+ - Project uses Mocha for mocking
1402
+ - Be careful with stubs - they can hide real issues
1403
+ - Verify mocks are being called as expected
1404
+ - Clean up stubs in teardown
1405
+
1406
+ **Test Naming:**
1407
+
1408
+ - Test names should describe behavior: `test_creates_new_branch`
1409
+ - Not implementation: `test_branch_method`
1410
+ - Good names make failures self-documenting
1411
+
1412
+ ### Integration with TDD Workflow
1413
+
1414
+ Test debugging transitions to TDD workflow in these cases:
1415
+
1416
+ 1. **Production Code Bug Found:**
1417
+ - Failing test = RED step already done
1418
+ - **→ Proceed to Phase 1: PREPARE**
1419
+ - Fix bug using GREEN step
1420
+ - Continue through Phase 2-3
1421
+
1422
+ 2. **Missing Test Coverage:**
1423
+ - **→ Proceed to Phase 1: PREPARE**
1424
+ - Write new tests using TDD cycle
1425
+ - RED → GREEN → REFACTOR for each test
1426
+
1427
+ 3. **Flaky Test Reveals Race Condition in Production Code:**
1428
+ - Fix test first to make deterministic
1429
+ - Then **→ Proceed to Phase 1: PREPARE** to fix production code
1430
+ - Write additional test for the race condition
1431
+ - Fix using TDD workflow
1432
+
1433
+ **Do NOT use TDD workflow for:**
1434
+
1435
+ - Updating tests after intentional API changes (direct test update)
1436
+ - Fixing flaky tests (test maintenance)
1437
+ - Refactoring tests (test cleanup)
1438
+ - Environment issues (no code changes)
1439
+
1440
+ ## Dependency Management Workflow
1441
+
1442
+ ### Project-Specific Rules
1443
+
1444
+ - **All dependencies go in `git.gemspec`** (both runtime and development) - enforced by Rubocop
1445
+ - **`Gemfile` should remain minimal/empty** - do not add dependencies here
1446
+ - **`Gemfile.lock` is NOT committed** - this is a gem/library project
1447
+
1448
+ ### Update Process
1449
+
1450
+ 1. **Assess:** Run `bundle outdated` and `bundle audit check --update` (if available)
1451
+ 2. **Update:** Edit `git.gemspec` if constraints need changing, then run `bundle update`
1452
+ 3. **Test:** Run `bundle exec rake default` - must pass on all Ruby versions (3.2, 3.3, 3.4)
1453
+ 4. **Commit:** Use conventional commit format:
1454
+ - Security: `fix(deps): update <gem> to fix CVE-XXXX-XXXX`
1455
+ - Regular: `chore(deps): update dependencies`
1456
+ - Breaking: `chore(deps)!: update <gem>` with `BREAKING CHANGE:` footer
1457
+
1458
+ ### Key Considerations
1459
+
1460
+ - Security vulnerabilities are highest priority - address immediately
1461
+ - For gem projects, version constraints in gemspec must be carefully chosen since users resolve dependencies independently
1462
+ - Breaking changes in dependencies may require code changes (use TDD workflow)
1463
+ - Test with both minimum supported versions and latest versions when possible
1464
+ - If tests fail, isolate by updating gems one at a time or use binary search
1465
+
1466
+ ### Commit Guidelines
1467
+
1468
+ This project uses [Conventional Commits](https://www.conventionalcommits.org/). A
1469
+ commit hook enforces the format. See [Git Commit
1470
+ Conventions](#git-commit-conventions) for the full format and allowed types.
1471
+
1472
+ #### Per-Task Commits
1473
+
1474
+ In the COMMIT step, create a commit for the completed task following these
1475
+ guidelines:
1476
+
1477
+ - **Use Appropriate Types:**
1478
+ - `test:` for adding or modifying tests (RED step)
1479
+ - `feat:` for new **user-facing** functionality (triggers MINOR version bump)
1480
+ - `fix:` for bug fixes (GREEN step for bugs)
1481
+ - `refactor:` for code improvements without behavior change
1482
+ - `chore:` for internal tooling or maintenance
1483
+ - **Use Scope When Relevant:** Include a scope to indicate the affected component
1484
+ (e.g., `feat(branch):`, `test(remote):`).
1485
+ - **Write Clear Subjects:** Use imperative mood, lowercase, no period (e.g.,
1486
+ `feat(branch): add create method`).
1487
+
1488
+ ### Additional Guidelines
1489
+
1490
+ These guidelines supplement the TDD process:
1491
+
1492
+ - **Justify Test Modifications:** If an existing test needs to be modified, STOP and
1493
+ report to the user before making the change. Explain which test needs modification,
1494
+ why the expected behavior is changing, and whether this represents a breaking
1495
+ change. Wait for user confirmation before proceeding.
1496
+ - **Unrelated Test Failures:** If you need to modify a test file that is not related
1497
+ to the current task to make the build pass, STOP and report to the user. This
1498
+ usually indicates a deeper regression, environment issue, or flawed assumption. Do
1499
+ not attempt to fix unrelated tests without user guidance.
1500
+ - **Handle Discovered Complexity:** If the implementation reveals a complex logic
1501
+ gap, add it to your task list but finish the current cycle first.
1502
+ - **Test Names Describe Behavior:** Name tests to clearly describe what behavior they
1503
+ verify (e.g., `test_creates_new_branch` not `test_branch`).
1504
+ - **Ask for Clarification:** Stop and ask for clarification if requirements or
1505
+ expectations are ambiguous.
1506
+
1507
+ ### Example TDD Cycle
1508
+
1509
+ Each task follows this cycle: **RED → GREEN → REFACTOR → VERIFY → COMMIT → REPLAN**
1510
+
1511
+ **RED:** Write a failing test that describes the desired behavior.
1512
+
1513
+ ```ruby
1514
+ def test_creates_new_branch
1515
+ @git.branch('feature').create
1516
+ assert @git.branches.local.map(&:name).include?('feature')
1517
+ end
1518
+ # Run: bundle exec bin/test test_branch → fails with NoMethodError
1519
+ ```
1520
+
1521
+ **GREEN:** Write minimal code to make the test pass.
1522
+
1523
+ ```ruby
1524
+ def create
1525
+ @base.lib.branch_new(@name)
1526
+ end
1527
+ # Run: bundle exec bin/test test_branch → passes
1528
+ ```
1529
+
1530
+ **REFACTOR:** Improve code quality without changing behavior, then run all tests.
1531
+
1532
+ **VERIFY:** Run `bundle exec rake default` to confirm tests and linters pass.
1533
+
1534
+ **COMMIT:** `git commit -m "feat(branch): add Branch#create method"`
1535
+
1536
+ **REPLAN:** Report progress, update task list, proceed to next task or FINALIZE.
1537
+
1538
+ **FINALIZE (after all tasks):** Propose squash commit with captured messages, wait
1539
+ for user confirmation, then execute.
1540
+
1541
+ ## Merge Conflict Resolution Workflow
1542
+
1543
+ This workflow guides resolving merge conflicts in pull requests or when merging
1544
+ branches locally.
1545
+
1546
+ ### Step 1: Identify Conflicts
1547
+
1548
+ Before resolving conflicts, understand what needs to be merged:
1549
+
1550
+ 1. **For PR conflicts:**
1551
+
1552
+ - View PR details and check out the PR branch using `gh pr checkout`
1553
+ - Attempt to merge `main` with `--no-commit` to see conflicts
1554
+
1555
+ 2. **For local branch merging:** Fetch origin, then attempt merge with
1556
+ `--no-commit` to see conflicts.
1557
+
1558
+ 3. **List conflicted files** using `git diff --name-only --diff-filter=U`.
1559
+
1560
+ ### Step 2: Understand the Conflicting Changes
1561
+
1562
+ For each conflicted file:
1563
+
1564
+ 1. **View the conflict markers** in the file.
1565
+ 2. **Understand both sides:** Compare what each branch changed relative to the
1566
+ common ancestor using `git diff` with the appropriate refs (HEAD, MERGE_HEAD,
1567
+ and the stage numbers `:1:`, `:2:`, `:3:` for base/ours/theirs).
1568
+ 3. **Check the history** of the conflicting sections if needed.
1569
+
1570
+ ### Step 3: Resolve Conflicts
1571
+
1572
+ Choose the appropriate resolution strategy:
1573
+
1574
+ - **Accept one side entirely:** Use `git checkout --ours <file>` or
1575
+ `git checkout --theirs <file>`
1576
+ - **Manual resolution:** Edit the file to resolve conflict markers
1577
+ (`<<<<<<<`, `=======`, `>>>>>>>`), then stage with `git add`
1578
+ - **Interactive merge tool:** Use `git mergetool <file>`
1579
+
1580
+ ### Step 4: Verify Resolution
1581
+
1582
+ After resolving all conflicts:
1583
+
1584
+ 1. **Check for remaining conflicts:** `git diff --check`
1585
+ 2. **Run the test suite:** `bundle exec bin/test`
1586
+ 3. **Run linters:** `bundle exec rake rubocop`
1587
+ 4. **Review the final diff:** `git diff --staged`
1588
+
1589
+ ### Step 5: Complete the Merge
1590
+
1591
+ Commit the merge with a message listing the resolved conflict files.
1592
+
1593
+ 1. **Push the changes:**
1594
+
1595
+ ```bash
1596
+ git push
1597
+ ```
1598
+
1599
+ 2. **For PRs, verify CI passes:**
1600
+
1601
+ ```bash
1602
+ gh pr checks #999
1603
+ ```
1604
+
1605
+ ## Code Archaeology & History Analysis Workflow
1606
+
1607
+ This workflow helps investigate code history to understand when bugs were introduced,
1608
+ track changes to specific code, and find usages of methods or classes.
1609
+
1610
+ ### Understanding History Analysis Tools
1611
+
1612
+ ruby-git provides several approaches to code archaeology:
1613
+
1614
+ - **git blame**: See who last modified each line
1615
+ - **git log**: Track commit history for files or code
1616
+ - **git bisect**: Binary search to find the commit that introduced a bug
1617
+ - **grep/semantic search**: Find usages of methods and classes
1618
+
1619
+ ### Finding When a Bug Was Introduced (git bisect)
1620
+
1621
+ When you need to find which commit introduced a bug:
1622
+
1623
+ 1. **Start bisect session:**
1624
+
1625
+ ```bash
1626
+ # Start bisect
1627
+ git bisect start
1628
+
1629
+ # Mark current commit as bad (has the bug)
1630
+ git bisect bad
1631
+
1632
+ # Mark a known good commit (before the bug existed)
1633
+ git bisect good <commit-sha>
1634
+ ```
1635
+
1636
+ 2. **Test each commit:**
1637
+
1638
+ For each commit git checks out:
1639
+
1640
+ ```bash
1641
+ # Run relevant tests
1642
+ bundle exec bin/test <test_name>
1643
+
1644
+ # Mark as good or bad
1645
+ git bisect good # if bug is NOT present
1646
+ git bisect bad # if bug IS present
1647
+ ```
1648
+
1649
+ 3. **Automated bisect with test script:**
1650
+
1651
+ ```bash
1652
+ # Create test script that exits 0 for good, non-zero for bad
1653
+ git bisect run bundle exec ruby -I lib:tests tests/units/test_specific.rb -n test_method
1654
+ ```
1655
+
1656
+ 4. **Complete bisect:**
1657
+
1658
+ ```bash
1659
+ # View the result
1660
+ git bisect log
1661
+
1662
+ # Reset to original state
1663
+ git bisect reset
1664
+ ```
1665
+
1666
+ ### Tracing Method History
1667
+
1668
+ To see how a specific method has changed over time:
1669
+
1670
+ 1. **View file history with changes:**
1671
+
1672
+ ```bash
1673
+ # Show commits that touched a specific file
1674
+ git log --oneline -p -- lib/git/base.rb
1675
+
1676
+ # Search for commits that changed specific text
1677
+ git log -p -S "def checkout" -- lib/git/base.rb
1678
+
1679
+ # Show commits that changed a specific function (if supported)
1680
+ git log -p -L :checkout:lib/git/base.rb
1681
+ ```
1682
+
1683
+ 2. **View the history of a specific line range:**
1684
+
1685
+ ```bash
1686
+ git log -p -L 100,150:lib/git/base.rb
1687
+ ```
1688
+
1689
+ 3. **Find when a method was added:**
1690
+
1691
+ ```bash
1692
+ git log --diff-filter=A -p -S "def method_name"
1693
+ ```
1694
+
1695
+ ### Finding Code Usages
1696
+
1697
+ To find all callers or usages of a method:
1698
+
1699
+ 1. **Use grep_search for exact matches:**
1700
+
1701
+ ```bash
1702
+ # Find method calls
1703
+ grep -rn "\.checkout" lib/ tests/
1704
+
1705
+ # Find class references
1706
+ grep -rn "Git::Base" lib/ tests/
1707
+ ```
1708
+
1709
+ 2. **Use semantic_search for broader context:**
1710
+
1711
+ Use the AI's semantic_search capability to find related code patterns.
1712
+
1713
+ 3. **Find test coverage for a method:**
1714
+
1715
+ ```bash
1716
+ grep -rn "def test.*checkout" tests/
1717
+ ```
1718
+
1719
+ ### Blame Analysis
1720
+
1721
+ To understand who changed specific code and why:
1722
+
1723
+ 1. **Basic blame:**
1724
+
1725
+ ```bash
1726
+ git blame lib/git/base.rb
1727
+ ```
1728
+
1729
+ 2. **Blame with commit messages:**
1730
+
1731
+ ```bash
1732
+ git blame -c lib/git/base.rb
1733
+ ```
1734
+
1735
+ 3. **Ignore whitespace changes:**
1736
+
1737
+ ```bash
1738
+ git blame -w lib/git/base.rb
1739
+ ```
1740
+
1741
+ 4. **Find the original author (ignore moves/copies):**
1742
+
1743
+ ```bash
1744
+ git blame -M -C lib/git/base.rb
1745
+ ```
1746
+
1747
+ 5. **Blame specific lines:**
1748
+
1749
+ ```bash
1750
+ git blame -L 100,150 lib/git/base.rb
1751
+ ```
1752
+
1753
+ ## Release Management Workflow
1754
+
1755
+ This workflow guides preparing and publishing new releases of the ruby-git gem.
1756
+
1757
+ ### Understanding the Release Process
1758
+
1759
+ ruby-git uses [release-please](https://github.com/googleapis/release-please) for
1760
+ automated release management. Key files:
1761
+
1762
+ - `release-please-config.json` - Release configuration
1763
+ - `lib/git/version.rb` - Version constant
1764
+ - `CHANGELOG.md` - Release history
1765
+
1766
+ ### Step 1: Pre-Release Checks
1767
+
1768
+ Before preparing a release:
1769
+
1770
+ 1. **Ensure all CI checks pass:**
1771
+
1772
+ ```bash
1773
+ bundle exec rake default
1774
+ ```
1775
+
1776
+ 2. **Review unreleased changes:**
1777
+
1778
+ ```bash
1779
+ # List commits since last tag
1780
+ git log $(git describe --tags --abbrev=0)..HEAD --oneline
1781
+
1782
+ # List PRs merged since last release
1783
+ gh pr list --state merged --base main --search "merged:>$(git log -1 --format=%cs $(git describe --tags --abbrev=0))"
1784
+ ```
1785
+
1786
+ 3. **Check for any outstanding issues:**
1787
+
1788
+ ```bash
1789
+ gh issue list --label "bug" --state open
1790
+ gh issue list --label "breaking-change" --state open
1791
+ ```
1792
+
1793
+ 4. **Verify documentation is current:**
1794
+
1795
+ ```bash
1796
+ bundle exec yard doc
1797
+ bundle exec yard stats --list-undoc
1798
+ ```
1799
+
1800
+ ### Step 2: Version Bump
1801
+
1802
+ Determine the appropriate version bump based on changes:
1803
+
1804
+ - **Patch** (x.y.Z): Bug fixes, documentation, non-breaking changes
1805
+ - **Minor** (x.Y.0): New features, backward-compatible additions
1806
+ - **Major** (X.0.0): Breaking changes
1807
+
1808
+ Update version in `lib/git/version.rb`:
1809
+
1810
+ ```ruby
1811
+ module Git
1812
+ VERSION = 'X.Y.Z'
1813
+ end
1814
+ ```
1815
+
1816
+ ### Step 3: Update Changelog
1817
+
1818
+ 1. **Generate release notes from PRs:**
1819
+
1820
+ ```bash
1821
+ # List merged PRs since last release
1822
+ gh pr list --state merged --base main --json number,title,labels,mergedAt \
1823
+ --search "merged:>$(git log -1 --format=%cs $(git describe --tags --abbrev=0))" \
1824
+ | jq -r '.[] | "- \(.title) (#\(.number))"'
1825
+ ```
1826
+
1827
+ 2. **Organize by category in CHANGELOG.md:**
1828
+
1829
+ ```markdown
1830
+ ## [X.Y.Z] - YYYY-MM-DD
1831
+
1832
+ ### Added
1833
+ - New feature description (#PR)
1834
+
1835
+ ### Changed
1836
+ - Changed behavior description (#PR)
1837
+
1838
+ ### Fixed
1839
+ - Bug fix description (#PR)
1840
+
1841
+ ### Deprecated
1842
+ - Deprecated feature description (#PR)
1843
+
1844
+ ### Removed
1845
+ - Removed feature description (#PR)
1846
+
1847
+ ### Security
1848
+ - Security fix description (#PR)
1849
+ ```
1850
+
1851
+ ### Step 4: Create Release
1852
+
1853
+ 1. **Commit version bump and changelog:**
1854
+
1855
+ ```bash
1856
+ git add lib/git/version.rb CHANGELOG.md
1857
+ git commit -m "chore: release X.Y.Z"
1858
+ ```
1859
+
1860
+ 2. **Create and push tag:**
1861
+
1862
+ ```bash
1863
+ git tag -a vX.Y.Z -m "Release X.Y.Z"
1864
+ git push origin main --tags
1865
+ ```
1866
+
1867
+ 3. **Build and publish gem:**
1868
+
1869
+ ```bash
1870
+ bundle exec rake build
1871
+ gem push pkg/git-X.Y.Z.gem
1872
+ ```
1873
+
1874
+ 4. **Create GitHub release:**
1875
+
1876
+ ```bash
1877
+ gh release create vX.Y.Z --title "vX.Y.Z" --notes-file RELEASE_NOTES.md
1878
+ ```
1879
+
1880
+ ### Step 5: Post-Release Tasks
1881
+
1882
+ 1. **Verify gem is available:**
1883
+
1884
+ ```bash
1885
+ gem info git --remote
1886
+ ```
1887
+
1888
+ 2. **Announce release (if applicable):**
1889
+ - Update any external documentation
1890
+ - Notify downstream dependencies
1891
+
1892
+ 3. **Close related milestone (if used):**
1893
+
1894
+ ```bash
1895
+ gh api repos/{owner}/{repo}/milestones --jq '.[] | select(.title=="vX.Y.Z")'
1896
+ ```
1897
+
1898
+ ### Release Commands Reference
1899
+
1900
+ ```bash
1901
+ # View recent tags
1902
+ git tag -l --sort=-v:refname | head -10
1903
+
1904
+ # Compare with previous release
1905
+ git diff v1.0.0..v1.1.0
1906
+
1907
+ # List commits since tag
1908
+ git log v1.0.0..HEAD --oneline
1909
+
1910
+ # View tag details
1911
+ git show v1.0.0
1912
+
1913
+ # Delete tag (if needed)
1914
+ git tag -d vX.Y.Z
1915
+ git push origin :refs/tags/vX.Y.Z
1916
+
1917
+ # Build gem locally
1918
+ bundle exec rake build
1919
+
1920
+ # Install gem locally for testing
1921
+ gem install pkg/git-X.Y.Z.gem
1922
+ ```
1923
+
1924
+ ## Breaking Change Analysis Workflow
1925
+
1926
+ This workflow helps assess the impact of API changes before implementation to
1927
+ understand what code would break and plan appropriate migration paths.
1928
+
1929
+ ### Understanding Breaking Changes
1930
+
1931
+ A breaking change is any modification that requires users to update their code:
1932
+
1933
+ - Removing or renaming public methods/classes
1934
+ - Changing method signatures (required parameters)
1935
+ - Changing return types or values
1936
+ - Changing exception types
1937
+ - Modifying default behavior
1938
+
1939
+ ### Step 1: Identify the Change Scope
1940
+
1941
+ 1. **Determine what is changing:**
1942
+
1943
+ - Which class(es) are affected?
1944
+ - Which method(s) are affected?
1945
+ - Is this a public or private API?
1946
+
1947
+ 2. **Check API visibility:**
1948
+
1949
+ ```bash
1950
+ # Search for @api tags in documentation
1951
+ grep -n "@api public" lib/git/*.rb
1952
+ grep -n "@api private" lib/git/*.rb
1953
+ ```
1954
+
1955
+ 3. **Review current documentation:**
1956
+
1957
+ ```bash
1958
+ bundle exec yard doc
1959
+ open doc/index.html
1960
+ ```
1961
+
1962
+ ### Step 2: Find All Usages
1963
+
1964
+ 1. **Search within the gem:**
1965
+
1966
+ ```bash
1967
+ # Find internal usages
1968
+ grep -rn "method_name" lib/
1969
+ grep -rn "ClassName" lib/
1970
+ ```
1971
+
1972
+ 2. **Search in tests:**
1973
+
1974
+ ```bash
1975
+ grep -rn "method_name" tests/
1976
+ ```
1977
+
1978
+ 3. **Use semantic search for broader patterns:**
1979
+
1980
+ Use the AI's semantic_search to find related usages that might not match exact
1981
+ patterns.
1982
+
1983
+ 4. **Check external usage (if applicable):**
1984
+
1985
+ ```bash
1986
+ # Search GitHub for usage of this gem's API
1987
+ gh search code "Git::Base#method_name language:ruby"
1988
+ ```
1989
+
1990
+ ### Step 3: Assess Impact
1991
+
1992
+ Create an impact assessment:
1993
+
1994
+ 1. **Internal impact:**
1995
+ - Number of files affected within the gem
1996
+ - Test changes required
1997
+ - Documentation updates needed
1998
+
1999
+ 2. **External impact:**
2000
+ - Likely number of external users affected
2001
+ - Severity (compile error vs. runtime error vs. behavior change)
2002
+ - Ease of migration
2003
+
2004
+ 3. **Document findings:**
2005
+
2006
+ ```markdown
2007
+ ## Breaking Change Impact Assessment
2008
+
2009
+ ### Change Description
2010
+ [What is being changed]
2011
+
2012
+ ### Affected API
2013
+ - Class: `Git::Base`
2014
+ - Method: `#checkout`
2015
+ - Current signature: `def checkout(branch, opts = {})`
2016
+ - Proposed signature: `def checkout(branch, create: false)`
2017
+
2018
+ ### Internal Impact
2019
+ - Files affected: X
2020
+ - Tests to update: Y
2021
+
2022
+ ### External Impact
2023
+ - Severity: [High/Medium/Low]
2024
+ - Migration difficulty: [Easy/Medium/Hard]
2025
+
2026
+ ### Migration Path
2027
+ [How users should update their code]
2028
+ ```
2029
+
2030
+ ### Step 4: Plan Migration Path
2031
+
2032
+ 1. **Deprecation approach (preferred for non-urgent changes):**
2033
+
2034
+ ```ruby
2035
+ def old_method(*args)
2036
+ warn "[DEPRECATION] `old_method` is deprecated. Use `new_method` instead."
2037
+ new_method(*args)
2038
+ end
2039
+ ```
2040
+
2041
+ 2. **Version-based migration:**
2042
+ - v2.x: Deprecate with warning
2043
+ - v3.0: Remove deprecated API
2044
+
2045
+ 3. **Document migration in CHANGELOG:**
2046
+
2047
+ ```markdown
2048
+ ### Deprecated
2049
+ - `Git::Base#old_method` is deprecated, use `Git::Base#new_method` instead
2050
+ ```
2051
+
2052
+ ### Step 5: Document the Change
2053
+
2054
+ 1. **Update YARD documentation:**
2055
+
2056
+ ```ruby
2057
+ # @deprecated Use {#new_method} instead. Will be removed in v3.0.
2058
+ def old_method
2059
+ end
2060
+ ```
2061
+
2062
+ 2. **Add to CHANGELOG.md:**
2063
+
2064
+ ````markdown
2065
+ ### Breaking Changes
2066
+ - `Git::Base#checkout` signature changed: `opts` hash replaced with keyword
2067
+ arguments
2068
+
2069
+ ### Migration Guide
2070
+
2071
+ Before:
2072
+
2073
+ ```ruby
2074
+ git.checkout('branch', { create: true })
2075
+ ```
2076
+
2077
+ After:
2078
+
2079
+ ```ruby
2080
+ git.checkout('branch', create: true)
2081
+ ```
2082
+ ````
2083
+
2084
+ 3. **Update README if applicable**
2085
+
2086
+ ## Documentation Workflow
2087
+
2088
+ This workflow guides creating and maintaining documentation for the ruby-git gem.
2089
+
2090
+ ### Understanding Documentation Standards
2091
+
2092
+ ruby-git uses YARD for API documentation:
2093
+
2094
+ - All public methods must have YARD documentation
2095
+ - Use standard YARD tags: `@param`, `@return`, `@raise`, `@example`
2096
+ - Include code examples for non-trivial methods
2097
+ - Document edge cases and platform differences
2098
+
2099
+ ### Step 1: Identify Documentation Gaps
2100
+
2101
+ 1. **Check documentation coverage:**
2102
+
2103
+ ```bash
2104
+ bundle exec yard stats --list-undoc
2105
+ ```
2106
+
2107
+ 2. **Find methods without documentation:**
2108
+
2109
+ ```bash
2110
+ bundle exec yard doc --no-output --no-cache 2>&1 | grep "Undocumented"
2111
+ ```
2112
+
2113
+ 3. **Review specific files:**
2114
+
2115
+ ```bash
2116
+ # Check documentation for a specific class
2117
+ bundle exec yard doc lib/git/base.rb --no-output
2118
+ ```
2119
+
2120
+ ### Step 2: Write Documentation
2121
+
2122
+ Follow the YARD documentation template:
2123
+
2124
+ ```ruby
2125
+ # Short description of what the method does
2126
+ #
2127
+ # Longer description with more details about behavior,
2128
+ # edge cases, or important notes.
2129
+ #
2130
+ # @param name [Type] Description of parameter
2131
+ # @param options [Hash] Options hash description
2132
+ # @option options [Type] :key Description of option
2133
+ #
2134
+ # @return [Type] Description of return value
2135
+ # @return [nil] When no result is found
2136
+ #
2137
+ # @raise [ArgumentError] When invalid arguments provided
2138
+ # @raise [Git::Error] When git command fails
2139
+ #
2140
+ # @example Basic usage
2141
+ # git = Git.open('/path/to/repo')
2142
+ # result = git.method_name('arg')
2143
+ #
2144
+ # @example With options
2145
+ # git.method_name('arg', option: true)
2146
+ #
2147
+ # @see #related_method
2148
+ # @see Git::RelatedClass
2149
+ #
2150
+ # @since 2.0.0
2151
+ # @api public
2152
+ def method_name(name, options = {})
2153
+ end
2154
+ ```
2155
+
2156
+ ### Step 3: Verify Documentation
2157
+
2158
+ 1. **Generate and review docs:**
2159
+
2160
+ ```bash
2161
+ bundle exec yard doc
2162
+ open doc/index.html
2163
+ ```
2164
+
2165
+ 2. **Check for warnings:**
2166
+
2167
+ ```bash
2168
+ bundle exec yard doc 2>&1 | grep -i "warn"
2169
+ ```
2170
+
2171
+ 3. **Verify examples work:**
2172
+
2173
+ Run code examples in a console to ensure they're correct:
2174
+
2175
+ ```bash
2176
+ bundle exec bin/console
2177
+ ```
2178
+
2179
+ 4. **Check cross-references:**
2180
+
2181
+ Verify all `@see` references point to valid targets.
2182
+
2183
+ ### Step 4: Update Related Documentation
2184
+
2185
+ 1. **README.md updates:**
2186
+ - Ensure examples match current API
2187
+ - Update feature descriptions
2188
+ - Check installation instructions
2189
+
2190
+ 2. **CHANGELOG.md entries:**
2191
+ - Document API changes
2192
+ - Note deprecations
2193
+
2194
+ 3. **Inline comments:**
2195
+ - Update implementation comments if behavior changed
2196
+ - Remove outdated TODO comments
2197
+
2198
+ ### Documentation Commands Reference
2199
+
2200
+ ```bash
2201
+ # Generate documentation
2202
+ bundle exec yard doc
2203
+
2204
+ # Generate and serve locally
2205
+ bundle exec yard server --reload
2206
+
2207
+ # Check documentation coverage
2208
+ bundle exec yard stats
2209
+
2210
+ # List undocumented objects
2211
+ bundle exec yard stats --list-undoc
2212
+
2213
+ # Generate docs for specific file
2214
+ bundle exec yard doc lib/git/base.rb
2215
+
2216
+ # Check for YARD syntax errors
2217
+ bundle exec yard doc --no-output 2>&1
2218
+
2219
+ # View documentation for specific class
2220
+ bundle exec yard ri Git::Base
2221
+ ```
2222
+
2223
+ ## Testing Requirements
2224
+
2225
+ ### Test Framework
2226
+
2227
+ - Use **Test::Unit** for all tests
2228
+ - Tests located in `tests/units/` directory
2229
+ - Test files named `test_*.rb`
2230
+ - Main test helper: `tests/test_helper.rb` provides utility methods
2231
+ - Uses Mocha for mocking
2232
+
2233
+ ### Coverage Target
2234
+
2235
+ Maintain **high code coverage** through TDD practice.
2236
+
2237
+ ### Test Organization
2238
+
2239
+ ```ruby
2240
+ require_relative '../test_helper'
2241
+
2242
+ class TestGitOpen < Test::Unit::TestCase
2243
+ def setup
2244
+ @repo = clone_working_repo
2245
+ end
2246
+
2247
+ def test_opens_existing_repository
2248
+ git = Git.open(@repo)
2249
+ assert_kind_of Git::Base, git
2250
+ end
2251
+
2252
+ def test_raises_on_invalid_path
2253
+ assert_raises(ArgumentError) do
2254
+ Git.open('/nonexistent/path')
2255
+ end
2256
+ end
2257
+ end
2258
+ ```
2259
+
2260
+ ### Critical Test Cases
2261
+
2262
+ - Repository operations (open, init, clone)
2263
+ - Branch operations (create, checkout, delete, merge)
2264
+ - Commit operations (add, commit, reset)
2265
+ - Remote operations (fetch, pull, push)
2266
+ - Status and diff operations
2267
+ - Log queries with various filters
2268
+ - Timeout handling for long-running operations
2269
+ - Error conditions (invalid repos, failed commands, timeouts)
2270
+ - Cross-platform compatibility (Mac, Linux, Windows)
2271
+ - Path handling with special characters and Unicode
2272
+ - Encoding issues with different character sets
2273
+ - Git version compatibility (minimum 2.28.0)
2274
+
2275
+ ### Test Helpers
2276
+
2277
+ The `Test::Unit::TestCase` base class provides:
2278
+
2279
+ - `clone_working_repo`: Creates a temporary clone of test repository
2280
+ - `create_temp_repo`: Creates a temporary repository for testing
2281
+ - `with_temp_dir`: Provides a temporary directory for tests
2282
+ - `git_teardown`: Automatically cleans up temporary files
2283
+ - Test fixtures in `tests/files/`
2284
+
2285
+ ### Running Tests
2286
+
2287
+ ```bash
2288
+ # Run all tests
2289
+ bundle exec bin/test
2290
+
2291
+ # Run specific test file using bin/test (preferred method)
2292
+ bundle exec bin/test test_base
2293
+
2294
+ # Run multiple test files
2295
+ bundle exec bin/test test_object test_archive
2296
+
2297
+ # Run specific test by name
2298
+ bundle exec ruby -I lib:tests tests/units/test_base.rb -n test_opens_existing_repository
2299
+
2300
+ # Run tests in Docker (tests against multiple Ruby versions)
2301
+ bin/test-in-docker
2302
+
2303
+ # View coverage report
2304
+ open coverage/index.html
2305
+ ```
2306
+
2307
+ ## Ruby and Git Version Compatibility
2308
+
2309
+ ### Current Support
2310
+
2311
+ - Minimum Ruby: 3.2.0
2312
+ - Minimum Git: 2.28.0 or greater
2313
+ - Actively tested on: MRI Ruby 3.2, 3.4, and 4.0
2314
+ - Platforms: Mac, Linux, Windows
2315
+ - CI tests on multiple Ruby versions and platforms
2316
+
2317
+ ### Dependencies
2318
+
2319
+ - `activesupport` (>= 5.0) - For utilities and deprecation handling
2320
+ - `addressable` (~> 2.8) - For URI parsing
2321
+ - `process_executer` (~> 4.0) - For subprocess execution with timeout
2322
+ - `rchardet` (~> 1.9) - For character encoding detection
2323
+
2324
+ ### Platform Considerations
2325
+
2326
+ **Cross-Platform Compatibility:**
2327
+
2328
+ - Git command execution works on all platforms
2329
+ - Handle Windows path separators and drive letters appropriately
2330
+ - Test Git operations on all platforms
2331
+ - Be aware of platform-specific Git behavior (e.g., line endings, permissions)
2332
+ - Windows has different path handling and file system behavior
2333
+
2334
+ **Git Version Compatibility:**
2335
+
2336
+ - Minimum Git version is 2.28.0
2337
+ - Test with different Git versions when using newer features
2338
+ - Gracefully handle missing Git features on older versions
2339
+ - Document Git version requirements for specific features
2340
+
2341
+ **Encoding Handling:**
2342
+
2343
+ - Handle different default encodings across platforms
2344
+ - Use `rchardet` for automatic encoding detection
2345
+ - Test with UTF-8 and other encodings
2346
+ - Binary vs. text mode differences on Windows
2347
+
2348
+ ## Configuration & Settings
2349
+
2350
+ ### Gemspec Configuration
2351
+
2352
+ Located in `git.gemspec`:
2353
+
2354
+ - Runtime dependencies: activesupport, addressable, process_executer, rchardet
2355
+ - Development dependencies: test-unit, mocha, rake, rubocop, yard, etc.
2356
+ - `required_ruby_version >= 3.2.0`
2357
+ - Git requirement: `git 2.28.0 or greater`
2358
+
2359
+ ### Rake Configuration
2360
+
2361
+ Located in `Rakefile`:
2362
+
2363
+ - Default task runs Test::Unit tests
2364
+ - Rubocop for linting
2365
+ - YARD for documentation generation
2366
+ - Tasks defined in `tasks/` directory
2367
+
2368
+ ## Error Handling
2369
+
2370
+ - Raise specific exception classes from `Git::Error` hierarchy
2371
+ - Always include relevant context (command, status, output) in exceptions
2372
+ - Provide helpful error messages that guide users to solutions
2373
+ - Handle platform-specific errors gracefully
2374
+ - Document all error conditions in method YARD docs
2375
+ - Never swallow exceptions silently
2376
+ - Use `ArgumentError` for invalid method arguments
2377
+
2378
+ **Error Design Principles:**
2379
+
2380
+ - Inherit from `Git::Error` for all gem-specific errors
2381
+ - `Git::FailedError`: Command failed (non-zero exit)
2382
+ - `Git::SignaledError`: Command killed by signal
2383
+ - `Git::TimeoutError`: Command exceeded timeout (subclass of SignaledError)
2384
+ - Include structured data (command, output, status) for debugging
2385
+ - Make errors programmatically inspectable
2386
+ - Distinguish between user errors and runtime errors
2387
+
2388
+ ## Performance Considerations
2389
+
2390
+ ### Git Commands
2391
+
2392
+ - Commands execute with configurable timeout (global or per-command)
2393
+ - Clean up resources properly
2394
+ - Handle large repository operations efficiently
2395
+ - Subprocess execution is handled internally by `Git::CommandLine`
2396
+
2397
+ ### Memory Management
2398
+
2399
+ - Lazy-load Git objects when possible
2400
+ - Stream large outputs rather than buffering everything
2401
+ - Be mindful of memory usage with large diffs and logs
2402
+ - Clean up temporary files and resources
2403
+
2404
+ ### Repository Operations
2405
+
2406
+ - Minimize Git command executions
2407
+ - Cache Git objects when appropriate
2408
+ - Use batch operations where possible
2409
+ - Consider performance implications of deep history traversal
2410
+
2411
+ ## Documentation
2412
+
2413
+ The purpose of this section is to define the standards for maintaining project
2414
+ documentation.
2415
+
2416
+ - Update README.md examples when API changes
2417
+ - Use inline YARD comments for comprehensive API documentation
2418
+ - Generate docs with `bundle exec yard doc`
2419
+ - Ensure examples in documentation actually work
2420
+ - Document platform-specific behavior
2421
+ - Document Git version requirements for features
2422
+ - Include security considerations (e.g., shell injection risks with certain
2423
+ operations)
2424
+
2425
+ ## Key Documents
2426
+
2427
+ Always consult these before implementing features:
2428
+
2429
+ - **README.md** - Project overview, usage examples, and getting started
2430
+ - **CHANGELOG.md** - Version history including identification breaking changes
2431
+ managed by the release GitHub Actions workflow
2432
+ - **LICENSE** - MIT License
2433
+ - **CONTRIBUTING.md** - Contribution guidelines
2434
+ - **MAINTAINERS.md** - Maintainer information
2435
+ - **redesign/** - Architecture redesign documentation
2436
+ - [The full YARD documentation page](https://rubydoc.info/gems/git/)
2437
+
2438
+ ## Code Quality Checklist
2439
+
2440
+ Before committing, ensure:
2441
+
2442
+ **Testing:**
2443
+
2444
+ - [ ] **TDD process followed** - Tests written before implementation
2445
+ - [ ] All tests pass (`bundle exec bin/test`)
2446
+ - [ ] No Ruby warnings when running tests
2447
+
2448
+ **Code Style:**
2449
+
2450
+ - [ ] Code follows Ruby style conventions (Rubocop)
2451
+ - [ ] YARD documentation for public methods
2452
+
2453
+ **Compatibility:**
2454
+
2455
+ - [ ] Backward compatibility maintained (unless breaking change)
2456
+ - [ ] Cross-platform compatibility considered (Windows, macOS, Linux)
2457
+ - [ ] Git version compatibility (minimum 2.28.0)
2458
+
2459
+ **Documentation & Safety:**
2460
+
2461
+ - [ ] Security considerations addressed (command injection, etc.)
2462
+ - [ ] Resource cleanup (file handles, temporary files)
2463
+
2464
+ ## Git Commit Conventions
2465
+
2466
+ **CRITICAL:** All commits **MUST** adhere to the [Conventional Commits
2467
+ standard](https://www.conventionalcommits.org/en/v1.0.0/). Commits not adhering to
2468
+ this standard will cause the CI build to fail. PRs will not be merged if they include
2469
+ non-conventional commits.
2470
+
2471
+ ### Conventional Commit Format
2472
+
2473
+ The simplest format: `type: description`
2474
+
2475
+ **Valid types** (see [.commitlintrc.yml](../.commitlintrc.yml) for full list):
2476
+
2477
+ - `feat:` - New user facing functionality
2478
+ - `fix:` - Bug fixes
2479
+ - `docs:` - Documentation only
2480
+ - `test:` - Adding/updating tests
2481
+ - `refactor:` - Code restructuring without changing behavior
2482
+ - `chore:` - Chores and maintenance (e.g., tooling, dependency bumps)
2483
+ - `perf:` - Performance improvements
2484
+ - `build:` - Build system or external dependency changes
2485
+ - `ci:` - Continuous integration configuration and scripts
2486
+ - `style:` - Code style and formatting only (no functional changes)
2487
+ - `revert:` - Revert a previous commit
2488
+
2489
+ **Description rules:**
2490
+
2491
+ 1. Must NOT start with an upper case letter
2492
+ 2. Must be no more than 100 characters
2493
+ 3. Must NOT end with punctuation
2494
+
2495
+ **Examples:**
2496
+
2497
+ - `feat: add the --merges option to Git::Lib.log`
2498
+ - `fix: exception thrown by Git::Lib.log when repo has no commits`
2499
+ - `docs: add conventional commit announcement to README.md`
2500
+
2501
+ **Breaking changes** must include an exclamation mark before the colon AND a
2502
+ `BREAKING CHANGE: <description>` footer where the `<description>` indicates what was
2503
+ broken:
2504
+
2505
+ - `feat!: removed Git::Base.commit_force`
2506
+
2507
+ Example with footer:
2508
+
2509
+ ```text
2510
+ feat(branch)!: rename create to make
2511
+
2512
+ Implement the new Branch#make method with improved validation.
2513
+
2514
+ BREAKING CHANGE: Branch#create renamed to Branch#make
2515
+ ```
2516
+
2517
+ **Full format:**
2518
+
2519
+ ```text
2520
+ type[optional scope][!]: description
2521
+
2522
+ [optional body]
2523
+
2524
+ [optional footer(s)]
2525
+ ```
2526
+
2527
+ **Version incrementing:**
2528
+
2529
+ - Breaking change → **major** version increment
2530
+ - New feature → **minor** version increment
2531
+ - Neither → **patch** version increment
2532
+
2533
+ **Pre-commit hook:** Run `bin/setup` in the project root to install a git pre-commit
2534
+ hook that validates conventional commit messages before pushing to GitHub.
2535
+
2536
+ This project uses [release-please](https://github.com/googleapis/release-please) for
2537
+ automated releases based on conventional commits.
2538
+
2539
+ ## Pull Request Guidelines
2540
+
2541
+ **Branch Strategy:**
2542
+
2543
+ 1. Ensure local main is up-to-date: `git fetch origin main`
2544
+ 2. Create a new branch from origin/main: `git checkout -b feature/your-feature
2545
+ origin/main`
2546
+ 3. Make your changes following TDD
2547
+ 4. Ensure all tests pass and code quality checks pass
2548
+ 5. Push the branch and create a PR
2549
+
2550
+ **When Submitting Existing Changes:**
2551
+
2552
+ - Ensure changes are on a feature branch (not `main`), following the naming
2553
+ convention `<type>/<short-description>`
2554
+ - If changes are on the wrong branch, offer to create a new branch from
2555
+ `origin/main` and relocate the user's existing work (commits or uncommitted
2556
+ changes) onto that new branch, choosing an appropriate Git approach (for
2557
+ example, cherry-pick, rebase, or recommitting) based on the situation
2558
+
2559
+ **PR Creation Automation:**
2560
+
2561
+ When asked to create the PR, use the GitHub CLI: `gh pr create --title "feat(scope):
2562
+ description" --body "..."`
2563
+
2564
+ - Read `.github/pull_request_template.md` to structure the body
2565
+ - Ensure the body covers the "PR Description Should Include" points below
2566
+ - Assign the user as the assignee if possible
2567
+
2568
+ **PR Description Should Include:**
2569
+
2570
+ - What problem does this solve?
2571
+ - What approach was taken?
2572
+ - Any breaking changes?
2573
+ - Testing performed (manual and automated)
2574
+ - Platform-specific considerations
2575
+ - Related issues/PRs
2576
+
2577
+ **Review Checklist:**
2578
+
2579
+ - All commits follow Conventional Commits standard (CI will fail otherwise)
2580
+ - Tests demonstrate the change works
2581
+ - All tests pass (`bundle exec rake default`)
2582
+ - Documentation updated (YARD comments for public methods)
2583
+ - CHANGELOG.md will be automatically updated by release-please
2584
+ - No breaking changes without major version bump or exclamation mark in commit
2585
+ - At least one approval from a project maintainer required before merge
2586
+
2587
+ ## PR Special Considerations
2588
+
2589
+ ### Security
2590
+
2591
+ - **Command Injection**: When using single-string commands, be aware of shell
2592
+ injection risks. Use `Git::CommandLine` for proper argument escaping.
2593
+ - **Input Validation**: Validate and sanitize user-supplied paths and arguments
2594
+ before passing to commands.
2595
+ - **File Permissions**: Be careful with file descriptors and permissions
2596
+ - **Resource Limits**: Consider timeout and resource consumption
2597
+ - **Git Hooks**: Consider risks associated with Git hook execution
2598
+ - Document security implications in YARD comments
2599
+
2600
+ ## Current Priorities
2601
+
2602
+ Based on project status and maintenance needs:
2603
+
2604
+ ### Stability and Compatibility
2605
+
2606
+ 1. Maintain Ruby 3.2+ compatibility
2607
+ 2. Keep cross-platform support (Mac, Linux, Windows)
2608
+ 3. Support Git 2.28.0+ versions
2609
+ 4. Ensure backward compatibility within major versions
2610
+
2611
+ ### Code Quality
2612
+
2613
+ 1. Maintain high test coverage
2614
+ 2. Follow TDD strictly for all changes
2615
+ 3. Keep Rubocop violations at zero
2616
+ 4. Comprehensive YARD documentation
2617
+
2618
+ ### Feature Enhancements
2619
+
2620
+ Consider these only after TDD test is written:
2621
+
2622
+ - Improved worktree support
2623
+ - Enhanced Git LFS integration
2624
+ - Better handling of large repositories
2625
+ - Performance optimizations for common operations
2626
+ - Additional Git operations as needed
2627
+
2628
+ ### Documentation Priorities
2629
+
2630
+ Focus on these specific documentation improvements to enhance developer experience
2631
+ and project maintainability:
2632
+
2633
+ - Keep README.md examples current and comprehensive
2634
+ - Add more real-world examples
2635
+ - Document common pitfalls and gotchas
2636
+ - Platform-specific behavior documentation
2637
+ - Complete architecture redesign documentation in `redesign/`
2638
+
2639
+ ## Useful Commands
2640
+
2641
+ See [Project Configuration](#project-configuration) for primary development commands.
2642
+
2643
+ **Additional commands:**
2644
+
2645
+ - Run specific test method: `bundle exec ruby -I lib:tests tests/units/test_base.rb -n test_method_name`
2646
+ - Run tests in Docker: `bin/test-in-docker`
2647
+ - Run with different Git: `GIT_PATH=/path/to/git/bin-wrappers bin/test`
2648
+ - Generate docs: `bundle exec yard doc`
2649
+ - Serve docs locally: `bundle exec yard server --reload`
2650
+ - Build gem: `bundle exec rake build`
2651
+ - Auto-fix style: `bundle exec rubocop -a`
2652
+
2653
+ ## Getting Help
2654
+
2655
+ - Review README.md for usage examples and architecture
2656
+ - Check CHANGELOG.md for version history and breaking changes
2657
+ - Read inline YARD documentation in source code
2658
+ - Browse full API docs on [the full YARD documentation
2659
+ page](https://rubydoc.info/gems/git/)
2660
+ - Look at existing tests for testing patterns
2661
+ - Check CI configuration in `.github/workflows/` for supported platforms
2662
+ - Review architecture redesign docs in `redesign/` directory
2663
+
2664
+ ## Important Implementation Notes
2665
+
2666
+ ### When Working with Git Commands
2667
+
2668
+ - Always use `Git::CommandLine` for command execution
2669
+ - Handle command output encoding properly
2670
+ - Consider timeout implications for long-running operations
2671
+ - Test with various Git versions (minimum 2.28.0)
2672
+ - Properly escape arguments and paths
2673
+ - Handle Git error messages and exit codes
2674
+
2675
+ ### When Working with Paths
2676
+
2677
+ - Use `Git::Path` for path handling
2678
+ - Use `Git::EscapedPath` for paths with special characters
2679
+ - Handle Windows path separators appropriately
2680
+ - Test with Unicode filenames
2681
+ - Consider relative vs. absolute paths
2682
+
2683
+ ### When Working with Repository Objects
2684
+
2685
+ - Lazy-load objects when possible
2686
+ - Cache objects appropriately
2687
+ - Handle missing or invalid objects gracefully
2688
+ - Test with various object types (commits, trees, blobs, tags)
2689
+ - Consider performance with large repositories
2690
+
2691
+ ### When Working with Encoding
2692
+
2693
+ - Use `rchardet` for encoding detection
2694
+ - Handle different platform encodings
2695
+ - Test with UTF-8, ASCII, and other encodings
2696
+ - Be aware of Git's encoding configuration
2697
+ - Handle binary files appropriately
2698
+
2699
+ ### When Working with Timeouts
2700
+
2701
+ - Use global timeout configuration or per-command overrides
2702
+ - Handle `Git::TimeoutError` appropriately
2703
+ - Test timeout behavior with long-running operations
2704
+ - Document timeout implications in YARD comments
2705
+ - Timeout support is built into the command execution layer