gac 0.16.1__tar.gz → 0.16.3__tar.gz

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.

Potentially problematic release.


This version of gac might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gac
3
- Version: 0.16.1
3
+ Version: 0.16.3
4
4
  Summary: AI-powered Git commit message generator with multi-provider support
5
5
  Project-URL: Homepage, https://github.com/cellwebb/gac
6
6
  Project-URL: Documentation, https://github.com/cellwebb/gac#readme
@@ -1,3 +1,3 @@
1
1
  """Version information for gac package."""
2
2
 
3
- __version__ = "0.16.1"
3
+ __version__ = "0.16.3"
@@ -102,8 +102,8 @@ class FileTypeImportance:
102
102
  ".ini": 3.5, # INI config
103
103
  ".env": 3.5, # Environment variables
104
104
  # Documentation
105
- ".md": 4.0, # Markdown
106
- ".rst": 3.8, # reStructuredText
105
+ ".md": 2.5, # Markdown (reduced to prioritize code changes)
106
+ ".rst": 2.5, # reStructuredText (reduced to prioritize code changes)
107
107
  # Web
108
108
  ".html": 3.5, # HTML
109
109
  ".css": 3.5, # CSS
@@ -127,12 +127,25 @@ def run_pre_commit_hooks() -> bool:
127
127
 
128
128
  # Run pre-commit hooks on staged files
129
129
  logger.info("Running pre-commit hooks...")
130
- try:
131
- run_subprocess(["pre-commit", "run"], silent=False, raise_on_error=True)
132
- # If we get here, all hooks passed
130
+ # Run pre-commit and capture both stdout and stderr
131
+ result = subprocess.run(["pre-commit", "run"], capture_output=True, text=True, check=False)
132
+
133
+ if result.returncode == 0:
134
+ # All hooks passed
133
135
  return True
134
- except subprocess.CalledProcessError as e:
135
- logger.error(f"Pre-commit hooks failed with exit code {e.returncode}")
136
+ else:
137
+ # Pre-commit hooks failed - show the output
138
+ output = result.stdout if result.stdout else ""
139
+ error = result.stderr if result.stderr else ""
140
+
141
+ # Combine outputs (pre-commit usually outputs to stdout)
142
+ full_output = output + ("\n" + error if error else "")
143
+
144
+ if full_output.strip():
145
+ # Show which hooks failed and why
146
+ logger.error(f"Pre-commit hooks failed:\n{full_output}")
147
+ else:
148
+ logger.error(f"Pre-commit hooks failed with exit code {result.returncode}")
136
149
  return False
137
150
  except Exception as e:
138
151
  logger.debug(f"Error running pre-commit: {e}")
@@ -15,6 +15,22 @@ DEFAULT_TEMPLATE = """<role>
15
15
  You are an expert git commit message generator. Your task is to analyze code changes and create a concise, meaningful git commit message. You will receive git status and diff information. Your entire response will be used directly as a git commit message.
16
16
  </role>
17
17
 
18
+ <focus>
19
+ Your commit message must reflect the core purpose and impact of these changes.
20
+ Prioritize the primary intent over implementation details.
21
+ Consider what future developers need to understand about this change.
22
+ Identify if this introduces new capabilities, fixes problems, or improves existing code.
23
+ </focus>
24
+
25
+ <mixed_changes>
26
+ When changes span multiple areas:
27
+ - Choose the commit type based on the PRIMARY purpose, not the largest file count
28
+ - Feature additions with supporting tests/docs should use 'feat'
29
+ - Bug fixes with added tests should use 'fix'
30
+ - Refactoring that improves multiple components should use 'refactor'
31
+ - Documentation updates are 'docs' only when that's the sole purpose
32
+ </mixed_changes>
33
+
18
34
  <format>
19
35
  <one_liner>
20
36
  Create a single-line commit message (50-72 characters if possible).
@@ -31,10 +47,17 @@ You are an expert git commit message generator. Your task is to analyze code cha
31
47
  </format>
32
48
 
33
49
  <conventions_no_scope>
34
- You MUST start your commit message with the most appropriate conventional commit prefix:
50
+ You MUST start your commit message with the most appropriate conventional commit prefix.
51
+
52
+ IMPORTANT: Check file types FIRST when determining the commit type:
53
+ - If changes are ONLY to documentation files (*.md, *.rst, *.txt in docs/, README*, CHANGELOG*, etc.), ALWAYS use 'docs:'
54
+ - Use 'docs:' ONLY when ALL changes are documentation files - INCLUDING README updates, regardless of how significant the changes are
55
+ - If changes include both documentation and code, use the prefix for the code changes, unless it is a documentation-only change
56
+
57
+ Commit type prefixes:
35
58
  - feat: A new feature or functionality addition
36
59
  - fix: A bug fix or error correction
37
- - docs: Documentation changes only
60
+ - docs: Documentation changes only (INCLUDING README updates, regardless of how significant)
38
61
  - style: Changes to code style/formatting without logic changes
39
62
  - refactor: Code restructuring without behavior changes
40
63
  - perf: Performance improvements
@@ -55,10 +78,14 @@ You MUST write a conventional commit message with EXACTLY ONE type and the REQUI
55
78
 
56
79
  FORMAT: type({scope}): description
57
80
 
81
+ IMPORTANT: Check file types FIRST when determining the commit type:
82
+ - If changes are ONLY to documentation files (*.md, *.rst, *.txt in docs/, README*, CHANGELOG*, etc.), ALWAYS use 'docs'
83
+ - If changes include both documentation and code, use the prefix for the code changes, unless it is a documentation-only change
84
+
58
85
  Select ONE type from this list that best matches the primary purpose of the changes:
59
86
  - feat: A new feature or functionality addition
60
87
  - fix: A bug fix or error correction
61
- - docs: Documentation changes only
88
+ - docs: Documentation changes only (INCLUDING README and CHANGELOG updates, regardless of how significant)
62
89
  - style: Changes to code style/formatting without logic changes
63
90
  - refactor: Code restructuring without behavior changes
64
91
  - perf: Performance improvements
@@ -87,10 +114,14 @@ You MUST write a conventional commit message with EXACTLY ONE type and an inferr
87
114
 
88
115
  FORMAT: type(scope): description
89
116
 
117
+ IMPORTANT: Check file types FIRST when determining the commit type:
118
+ - If changes are ONLY to documentation files (*.md, *.rst, *.txt in docs/, README*, CHANGELOG*, etc.), ALWAYS use 'docs'
119
+ - If changes include both documentation and code, use the prefix for the code changes, unless it is a documentation-only change
120
+
90
121
  Select ONE type from this list that best matches the primary purpose of the changes:
91
122
  - feat: A new feature or functionality addition
92
123
  - fix: A bug fix or error correction
93
- - docs: Documentation changes only
124
+ - docs: Documentation changes only (INCLUDING README and CHANGELOG updates, regardless of how significant)
94
125
  - style: Changes to code style/formatting without logic changes
95
126
  - refactor: Code restructuring without behavior changes
96
127
  - perf: Performance improvements
@@ -100,6 +131,16 @@ Select ONE type from this list that best matches the primary purpose of the chan
100
131
  - chore: Miscellaneous changes not affecting src/test files
101
132
 
102
133
  You MUST infer an appropriate scope from the changes. A good scope is concise (usually one word) and indicates the component or area that was changed.
134
+
135
+ <scope_rules>
136
+ For scope inference, select the most specific component affected:
137
+ - Use module/component names from the codebase (auth, api, cli, core)
138
+ - Use functional areas for cross-cutting changes (config, build, test)
139
+ - Keep scopes consistent with existing commit history when possible
140
+ - Prefer established patterns over creating new scope names
141
+ - Use singular form (auth, not auths; test, not tests)
142
+ </scope_rules>
143
+
103
144
  Examples of good scopes: api, auth, ui, core, docs, build, prompt, config
104
145
 
105
146
  CORRECT EXAMPLES (these formats are correct):
@@ -133,6 +174,44 @@ Additional context provided by the user: <hint_text></hint_text>
133
174
  <diff></diff>
134
175
  </git_diff>
135
176
 
177
+
178
+
179
+ <examples_no_scope>
180
+ Good commit messages (no scope):
181
+ [OK] feat: add OAuth2 integration with Google and GitHub
182
+ [OK] fix: resolve race condition in user session management
183
+ [OK] docs: add troubleshooting section for common installation issues
184
+ [OK] refactor: extract validation logic into reusable utilities
185
+ [OK] test: add comprehensive unit tests for token validation
186
+ [OK] build: upgrade to latest security patches
187
+
188
+ Bad commit messages:
189
+ [ERROR] fix stuff
190
+ [ERROR] update code
191
+ [ERROR] feat(auth): add login (scope included when not requested)
192
+ [ERROR] WIP: still working on this
193
+ [ERROR] Fixed bug
194
+ [ERROR] Changes
195
+ </examples_no_scope>
196
+
197
+ <examples_with_scope>
198
+ Good commit messages (with scope):
199
+ [OK] feat(auth): add OAuth2 integration with Google and GitHub
200
+ [OK] fix(api): resolve race condition in user session management
201
+ [OK] docs(readme): add troubleshooting section for common installation issues
202
+ [OK] refactor(core): extract validation logic into reusable utilities
203
+ [OK] test(auth): add comprehensive unit tests for token validation
204
+ [OK] build(deps): upgrade to latest security patches
205
+
206
+ Bad commit messages:
207
+ [ERROR] fix stuff
208
+ [ERROR] update code
209
+ [ERROR] feat: fix(auth): add login (double prefix)
210
+ [ERROR] WIP: still working on this
211
+ [ERROR] Fixed bug
212
+ [ERROR] Changes
213
+ </examples_with_scope>
214
+
136
215
  <instructions>
137
216
  IMMEDIATELY AFTER ANALYZING THE CHANGES, RESPOND WITH ONLY THE COMMIT MESSAGE.
138
217
  DO NOT include any preamble, reasoning, explanations or anything other than the commit message itself.
@@ -237,6 +316,18 @@ def build_prompt(
237
316
  else:
238
317
  template = re.sub(r"<one_liner>.*?</one_liner>", "", template, flags=re.DOTALL)
239
318
 
319
+ # Clean up examples sections based on scope settings
320
+ if scope is None:
321
+ # No scope - keep no_scope examples, remove scope examples
322
+ template = re.sub(r"<examples_with_scope>.*?</examples_with_scope>\n?", "", template, flags=re.DOTALL)
323
+ template = template.replace("<examples_no_scope>", "<examples>")
324
+ template = template.replace("</examples_no_scope>", "</examples>")
325
+ else:
326
+ # With scope (either provided or inferred) - keep scope examples, remove no_scope examples
327
+ template = re.sub(r"<examples_no_scope>.*?</examples_no_scope>\n?", "", template, flags=re.DOTALL)
328
+ template = template.replace("<examples_with_scope>", "<examples>")
329
+ template = template.replace("</examples_with_scope>", "</examples>")
330
+
240
331
  # Clean up extra whitespace, collapsing blank lines that may contain spaces
241
332
  template = re.sub(r"\n(?:[ \t]*\n){2,}", "\n\n", template)
242
333
 
@@ -102,12 +102,12 @@ def run_subprocess(
102
102
  timeout=timeout,
103
103
  )
104
104
 
105
- if result.returncode != 0 and (check or raise_on_error):
105
+ should_raise = result.returncode != 0 and (check or raise_on_error)
106
+
107
+ if should_raise:
106
108
  if not silent:
107
109
  logger.debug(f"Command stderr: {result.stderr}")
108
-
109
- error = subprocess.CalledProcessError(result.returncode, command, result.stdout, result.stderr)
110
- raise error
110
+ raise subprocess.CalledProcessError(result.returncode, command, result.stdout, result.stderr)
111
111
 
112
112
  output = result.stdout
113
113
  if strip_output:
@@ -119,7 +119,7 @@ def run_subprocess(
119
119
  raise GacError(f"Command timed out: {' '.join(command)}") from e
120
120
  except subprocess.CalledProcessError as e:
121
121
  if not silent:
122
- logger.error(f"Command failed: {e.stderr.strip() if hasattr(e, 'stderr') else str(e)}")
122
+ logger.error(f"Command failed: {e.stderr.strip() if e.stderr else str(e)}")
123
123
  if raise_on_error:
124
124
  raise
125
125
  return ""
@@ -128,6 +128,5 @@ def run_subprocess(
128
128
  logger.debug(f"Command error: {e}")
129
129
  if raise_on_error:
130
130
  # Convert generic exceptions to CalledProcessError for consistency
131
- error = subprocess.CalledProcessError(1, command, "", str(e))
132
- raise error from e
131
+ raise subprocess.CalledProcessError(1, command, "", str(e)) from e
133
132
  return ""
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes