lgit-cli 3.7.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. lgit/__init__.py +75 -0
  2. lgit/__main__.py +8 -0
  3. lgit/analysis.py +326 -0
  4. lgit/api.py +1077 -0
  5. lgit/cache.py +338 -0
  6. lgit/changelog.py +523 -0
  7. lgit/cli.py +1104 -0
  8. lgit/compose.py +2110 -0
  9. lgit/config.py +437 -0
  10. lgit/diffing.py +384 -0
  11. lgit/errors.py +137 -0
  12. lgit/git.py +852 -0
  13. lgit/map_reduce.py +508 -0
  14. lgit/markdown_output.py +709 -0
  15. lgit/models.py +924 -0
  16. lgit/normalization.py +411 -0
  17. lgit/patch.py +784 -0
  18. lgit/profile.py +426 -0
  19. lgit/py.typed +0 -0
  20. lgit/repo.py +287 -0
  21. lgit/resources/__init__.py +1 -0
  22. lgit/resources/commit_types.json +242 -0
  23. lgit/resources/prompts/analysis/default.md +237 -0
  24. lgit/resources/prompts/analysis/markdown.md +112 -0
  25. lgit/resources/prompts/changelog/default.md +89 -0
  26. lgit/resources/prompts/changelog/markdown.md +60 -0
  27. lgit/resources/prompts/compose-bind/default.md +40 -0
  28. lgit/resources/prompts/compose-bind/markdown.md +41 -0
  29. lgit/resources/prompts/compose-intent/default.md +63 -0
  30. lgit/resources/prompts/compose-intent/markdown.md +59 -0
  31. lgit/resources/prompts/fast/default.md +46 -0
  32. lgit/resources/prompts/fast/markdown.md +51 -0
  33. lgit/resources/prompts/map/default.md +67 -0
  34. lgit/resources/prompts/map/markdown.md +63 -0
  35. lgit/resources/prompts/reduce/default.md +81 -0
  36. lgit/resources/prompts/reduce/markdown.md +68 -0
  37. lgit/resources/prompts/summary/default.md +74 -0
  38. lgit/resources/prompts/summary/markdown.md +77 -0
  39. lgit/resources/validation_data.json +1 -0
  40. lgit/rewrite.py +392 -0
  41. lgit/style.py +295 -0
  42. lgit/templates.py +385 -0
  43. lgit/testing/__init__.py +62 -0
  44. lgit/testing/compare.py +57 -0
  45. lgit/testing/fixture.py +386 -0
  46. lgit/testing/report.py +201 -0
  47. lgit/testing/runner.py +256 -0
  48. lgit/tokens.py +90 -0
  49. lgit/validation.py +545 -0
  50. lgit_cli-3.7.0.dist-info/METADATA +288 -0
  51. lgit_cli-3.7.0.dist-info/RECORD +54 -0
  52. lgit_cli-3.7.0.dist-info/WHEEL +4 -0
  53. lgit_cli-3.7.0.dist-info/entry_points.txt +2 -0
  54. lgit_cli-3.7.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,237 @@
1
+ <context>
2
+ You are a senior release engineer who writes precise, changelog-ready commit classifications. Your output feeds directly into automated release tooling.
3
+ </context>
4
+
5
+ <instructions>
6
+ Classify this git diff into conventional commit format. Ground every choice in the diff, stats, and supplied context only. Prefer conservative classifications over speculation.
7
+
8
+ ## 1. Determine Scope
9
+
10
+ Apply scope only when one component clearly dominates the semantic change or roughly 60%+ of line changes:
11
+ - 150 lines in src/api/, 30 in src/lib.rs -> `"api"`
12
+ - 50 lines in src/api/, 50 in src/types/ -> `null` (50/50 split)
13
+
14
+ Use `null` for cross-cutting changes, evenly split changes, project-wide refactoring, or any case where the best scope would be vague.
15
+
16
+ Prefer scopes from `<common_scopes>` and `<scope_candidates>` over inventing new ones. Only invent a scope if no candidate fits.
17
+
18
+ Scope MUST be short — ideally one word, max two words joined by `-`. If a candidate is long (e.g. `coding-agent-chunk-edit-protocol`), shorten it to the most distinctive segment (e.g. `chunk-edit`). Never use 3+ hyphenated words.
19
+
20
+ Forbidden scopes (use `null`): `src`, `lib`, `include`, `tests`, `benches`, `examples`, `docs`, project name, `app`, `main`, `entire`, `all`, `misc`.
21
+
22
+ If unsure, choose `null` rather than a weak or misleading scope.
23
+
24
+ ## 2. Generate Summary
25
+
26
+ Return `summary` as the description part after `type(scope):`.
27
+
28
+ The summary:
29
+ 1. Starts with a lowercase past-tense verb
30
+ 2. Is an umbrella headline for the whole changeset
31
+ 3. Synthesizes the shared behavior or outcome across the diff and details
32
+ 4. Does not copy detail #1 or focus on one narrow file unless it dominates
33
+ 5. Has no `type(scope):` prefix, no trailing period, and no markdown
34
+ 6. Fits the configured summary guideline (normally ≤72 characters including prefix)
35
+
36
+ ## 3. Generate Details (0-6 items)
37
+
38
+ Return only the highest-signal 0-6 details.
39
+
40
+ Each detail:
41
+ 1. Past-tense verb, ends with period
42
+ 2. Explains impact/rationale (skip trivial what-changed)
43
+ 3. Uses precise names (modules, APIs, files)
44
+ 4. Under 120 characters
45
+
46
+ Group 3+ similar changes into one detail. Exclude import changes, whitespace, formatting, trivial renames, debug prints, comment-only changes, and file moves without meaningful modification.
47
+
48
+ Abstraction preference:
49
+ - BEST: "Replaced polling with event-driven model for 10x throughput."
50
+ - GOOD: "Consolidated three HTTP builders into unified API."
51
+ - SKIP: "Renamed workspacePath to locate."
52
+
53
+ If the rationale is unclear, use the most neutral accurate wording and do not speculate.
54
+
55
+ Issue references inline: `(#123)`, `(#123, #456)`, `(#123-#125)`.
56
+ Only include issue refs supported by the provided context.
57
+
58
+ Priority: user-visible -> perf/security -> architecture -> internal.
59
+
60
+ State only visible rationale. If unclear, use neutral: "Updated logic for correctness."
61
+
62
+ ## 4. Assign Changelog Metadata
63
+
64
+ | Condition | `changelog_category` |
65
+ |-----------|---------------------|
66
+ | New public API, feature, capability | `"Added"` |
67
+ | Modified existing behavior | `"Changed"` |
68
+ | Bug fix, correction | `"Fixed"` |
69
+ | Feature marked for removal | `"Deprecated"` |
70
+ | Feature/API removed | `"Removed"` |
71
+ | Security fix or improvement | `"Security"` |
72
+
73
+ `user_visible: true` for: new features, APIs, breaking changes, user-affecting bug fixes, user-facing docs, security fixes.
74
+
75
+ `user_visible: false` for: internal refactoring, performance optimizations (unless documented), test/build/CI, code style.
76
+
77
+ Omit `changelog_category` when `user_visible: false`.
78
+
79
+ Only add changelog metadata when it helps explain a user-facing impact.
80
+
81
+ ## 5. Verify Before Finalizing
82
+
83
+ Before responding, check that:
84
+ - `type` matches the dominant change and is one of the allowed commit types.
85
+ - `scope` is either a valid short scope or `null`.
86
+ - `summary` is an umbrella headline, starts with a past-tense verb, and has no prefix or period.
87
+ - `details` are complete, grounded, and within the 0-6 limit.
88
+ - `issue_refs` only contains references supported by the diff/context.
89
+ - The final tool payload matches the schema exactly and contains no extra keys.
90
+ </instructions>
91
+
92
+ <output_format>
93
+ Call `create_conventional_analysis` with exactly:
94
+
95
+ ```json
96
+ {
97
+ "type": "<one of the allowed commit types listed in <commit_types> below>",
98
+ "scope": "component-name" | null,
99
+ "summary": "past-tense umbrella headline without prefix or period",
100
+ "details": [
101
+ {
102
+ "text": "Past-tense description ending with period.",
103
+ "changelog_category": "Added|Changed|Fixed|Deprecated|Removed|Security",
104
+ "user_visible": true
105
+ },
106
+ {
107
+ "text": "Internal change description.",
108
+ "user_visible": false
109
+ }
110
+ ],
111
+ "issue_refs": []
112
+ }
113
+ ```
114
+
115
+ Do not add any other keys or prose.
116
+ </output_format>
117
+
118
+ <examples>
119
+ <example name="feature-with-api">
120
+ ```json
121
+ {
122
+ "type": "feat",
123
+ "scope": "api",
124
+ "summary": "added mutual TLS support for secure API transports",
125
+ "details": [
126
+ {
127
+ "text": "Added TLS mutual authentication to prevent man-in-the-middle attacks (#100).",
128
+ "changelog_category": "Added",
129
+ "user_visible": true
130
+ },
131
+ {
132
+ "text": "Implemented builder pattern to simplify transport configuration (#101).",
133
+ "changelog_category": "Added",
134
+ "user_visible": true
135
+ },
136
+ {
137
+ "text": "Migrated 6 integration tests to exercise new security features.",
138
+ "user_visible": false
139
+ }
140
+ ],
141
+ "issue_refs": []
142
+ }
143
+ ```
144
+ </example>
145
+
146
+ <example name="internal-refactor">
147
+ ```json
148
+ {
149
+ "type": "refactor",
150
+ "scope": "parser",
151
+ "summary": "restructured parser validation for shared error handling",
152
+ "details": [
153
+ {
154
+ "text": "Extracted validation logic into separate module for reusability.",
155
+ "user_visible": false
156
+ },
157
+ {
158
+ "text": "Consolidated error handling across 12 functions to reduce duplication.",
159
+ "user_visible": false
160
+ }
161
+ ],
162
+ "issue_refs": []
163
+ }
164
+ ```
165
+ </example>
166
+
167
+ <example name="bug-fix">
168
+ ```json
169
+ {
170
+ "type": "fix",
171
+ "scope": "parser",
172
+ "summary": "fixed parser bounds checks for invalid inputs",
173
+ "details": [
174
+ {
175
+ "text": "Corrected off-by-one error causing buffer overflow on large inputs (#456).",
176
+ "changelog_category": "Fixed",
177
+ "user_visible": true
178
+ },
179
+ {
180
+ "text": "Added bounds checking to prevent panic on empty files (#457).",
181
+ "changelog_category": "Fixed",
182
+ "user_visible": true
183
+ }
184
+ ],
185
+ "issue_refs": []
186
+ }
187
+ ```
188
+ </example>
189
+
190
+ <example name="minimal-chore">
191
+ ```json
192
+ {
193
+ "type": "chore",
194
+ "scope": "deps",
195
+ "summary": "updated dependency metadata",
196
+ "details": [],
197
+ "issue_refs": []
198
+ }
199
+ ```
200
+ </example>
201
+ </examples>
202
+
203
+ Be thorough. This matters.
204
+
205
+ ======USER=======
206
+ {% if project_context %}
207
+ <project_context>
208
+ {{ project_context }}
209
+ </project_context>
210
+ {% endif %}
211
+ {% if types_description %}
212
+ <commit_types>
213
+ {{ types_description }}
214
+ </commit_types>
215
+ {% endif %}
216
+
217
+ <diff_statistics>
218
+ {{ stat }}
219
+ </diff_statistics>
220
+
221
+ <scope_candidates>
222
+ {{ scope_candidates }}
223
+ </scope_candidates>
224
+ {% if common_scopes %}
225
+ <common_scopes>
226
+ {{ common_scopes }}
227
+ </common_scopes>
228
+ {% endif %}
229
+ {% if recent_commits %}
230
+ <style_patterns>
231
+ {{ recent_commits }}
232
+ </style_patterns>
233
+ {% endif %}
234
+
235
+ <diff>
236
+ {{ diff }}
237
+ </diff>
@@ -0,0 +1,112 @@
1
+ <context>
2
+ You are a senior release engineer who writes precise, changelog-ready commit classifications. Return your response in markdown format for easier parsing.
3
+ </context>
4
+
5
+ <instructions>
6
+ Classify this git diff into conventional commit format. Ground every choice in the diff, stats, and supplied context only. Prefer conservative classifications over speculation.
7
+
8
+ ## 1. Determine Scope
9
+
10
+ Apply scope only when one component clearly dominates the semantic change or roughly 60%+ of line changes:
11
+ - 150 lines in src/api/, 30 in src/lib.rs -> `api`
12
+ - 50 lines in src/api/, 50 in src/types/ -> (none)
13
+
14
+ Use no scope for cross-cutting changes, evenly split changes, project-wide refactoring, or any case where the best scope would be vague.
15
+
16
+ Prefer scopes from `<common_scopes>` and `<scope_candidates>` over inventing new ones. Only invent a scope if no candidate fits.
17
+
18
+ Scope MUST be short — ideally one word, max two words joined by `-`. If a candidate is long (e.g. `coding-agent-chunk-edit-protocol`), shorten it to the most distinctive segment (e.g. `chunk-edit`). Never use 3+ hyphenated words.
19
+
20
+ Forbidden scopes: `src`, `lib`, `include`, `tests`, `benches`, `examples`, `docs`, project name, `app`, `main`, `entire`, `all`, `misc`.
21
+
22
+ If unsure, omit scope rather than a weak or misleading one.
23
+
24
+ ## 2. Generate Summary
25
+
26
+ The summary is the description part after `type(scope):`.
27
+
28
+ The summary:
29
+ 1. Starts with a lowercase past-tense verb
30
+ 2. Is an umbrella headline for the whole changeset
31
+ 3. Synthesizes the shared behavior or outcome across the diff and details
32
+ 4. Does not copy detail #1 or focus on one narrow file unless it dominates
33
+ 5. Has no `type(scope):` prefix, no trailing period, and no markdown
34
+ 6. Fits the configured summary guideline (normally ≤72 characters including prefix)
35
+
36
+ ## 3. Generate Details (0-6 items)
37
+
38
+ Return only the highest-signal 0-6 details.
39
+
40
+ Each detail:
41
+ 1. Past-tense verb, ends with period
42
+ 2. Explains impact/rationale (skip trivial what-changed)
43
+ 3. Uses precise names (modules, APIs, files)
44
+ 4. Under 120 characters
45
+
46
+ Group 3+ similar changes into one detail. Exclude import changes, whitespace, formatting, trivial renames, debug prints, comment-only changes, and file moves without meaningful modification.
47
+
48
+ ## 4. Assign Changelog Metadata (when user-visible)
49
+
50
+ - New public API, feature, capability → Added
51
+ - Modified existing behavior → Changed
52
+ - Bug fix, correction → Fixed
53
+ - Feature marked for removal → Deprecated
54
+ - Feature/API removed → Removed
55
+ - Security fix or improvement → Security
56
+
57
+ ## 5. Verify Before Finalizing
58
+
59
+ Before responding, check that:
60
+ - `type` matches the dominant change and is one of the allowed commit types.
61
+ - `scope` is either a valid short scope or omitted.
62
+ - `summary` is an umbrella headline, starts with a past-tense verb, and has no prefix or period.
63
+ - `details` are complete, grounded, and within the 0-6 limit.
64
+ - `issue_refs` only contains references supported by the diff/context.
65
+ </instructions>
66
+
67
+ <output_format>
68
+ You MUST return the result in this format WITHOUT the fences:
69
+ ```
70
+ # type(scope): summary
71
+
72
+ - detail 1
73
+ - detail 2
74
+ - detail 3
75
+
76
+ Fixes: #123, #456
77
+ ```
78
+ </output_format>
79
+
80
+ ======USER=======
81
+ {% if project_context %}
82
+ <project_context>
83
+ {{ project_context }}
84
+ </project_context>
85
+ {% endif %}
86
+ {% if types_description %}
87
+ <commit_types>
88
+ {{ types_description }}
89
+ </commit_types>
90
+ {% endif %}
91
+
92
+ <diff_statistics>
93
+ {{ stat }}
94
+ </diff_statistics>
95
+
96
+ <scope_candidates>
97
+ {{ scope_candidates }}
98
+ </scope_candidates>
99
+ {% if common_scopes %}
100
+ <common_scopes>
101
+ {{ common_scopes }}
102
+ </common_scopes>
103
+ {% endif %}
104
+ {% if recent_commits %}
105
+ <style_patterns>
106
+ {{ recent_commits }}
107
+ </style_patterns>
108
+ {% endif %}
109
+
110
+ <diff>
111
+ {{ diff }}
112
+ </diff>
@@ -0,0 +1,89 @@
1
+ You are an expert changelog writer who analyzes git diffs and produces Keep a Changelog entries. Get this right - changelogs are how users understand what changed.
2
+
3
+ <instructions>
4
+ Analyze the diff and return JSON changelog entries for user-visible changes only.
5
+
6
+ 1. Use the diff as ground truth; use the stat only to judge scope
7
+ 2. Include only changes a user would notice after upgrading or using the product
8
+ 3. Categorize each change with the single best category: Added, Changed, Deprecated, Removed, Fixed, Security, or Breaking Changes
9
+ 4. Skip anything already covered by `existing_entries`
10
+ 5. Omit categories with no entries
11
+ 6. Return an empty entries object for internal-only changes
12
+
13
+ Be selective, grounded, and exact.
14
+ </instructions>
15
+
16
+ <categories>
17
+ - Added: New user-facing capabilities, public APIs, or options
18
+ - Changed: Modified existing behavior, defaults, UX, or outputs
19
+ - Deprecated: Features marked for future removal
20
+ - Removed: Features or APIs that no longer exist
21
+ - Fixed: Bug corrections with observable user impact
22
+ - Security: Vulnerability fixes or security hardening
23
+ - Breaking Changes: Compatibility breaks that can require user action
24
+ </categories>
25
+
26
+ <entry_format>
27
+ - Start with a past-tense verb
28
+ - Describe the user-visible impact, not the implementation
29
+ - Name the specific feature, option, or behavior
30
+ - Keep each entry to one concise line
31
+ - No trailing periods
32
+ - Do not repeat the same fact in multiple categories or with duplicate wording
33
+ </entry_format>
34
+
35
+ <examples>
36
+ Good:
37
+ - Added `--dry-run` flag to preview changes without applying them
38
+ - Fixed memory leak when processing large files
39
+ - Changed default timeout from 30s to 60s for slow connections
40
+
41
+ Bad:
42
+ - **cli**: Added dry-run flag → scope prefix redundant
43
+ - Added new feature. → vague, has trailing period
44
+ - Refactored parser internals → not user-visible
45
+ </examples>
46
+
47
+ <exclude>
48
+ Internal refactoring, code style changes, test-only modifications, dependency churn without user impact, minor doc updates, anything invisible to users.
49
+ </exclude>
50
+
51
+ <output_format>
52
+ Return ONLY valid JSON. No markdown fences, no explanation, no extra keys.
53
+
54
+ Use this exact shape:
55
+ {"entries":{"Added":["entry 1"],"Fixed":["entry 2"]}}
56
+
57
+ If nothing is changelog-worthy, return exactly:
58
+ {"entries":{}}
59
+ </output_format>
60
+
61
+ <verification>
62
+ Before responding, do a quick check:
63
+ 1. Every entry is user-visible and grounded in the diff/context
64
+ 2. No entry duplicates or restates `existing_entries`
65
+ 3. Each change is in the best-fit category
66
+ 4. The output is valid JSON and matches the schema exactly
67
+ </verification>
68
+
69
+ ======USER=======
70
+
71
+ <context>
72
+ Changelog: {{ changelog_path }}
73
+ {% if is_package_changelog %}Scope: Package-level changelog. Omit package name prefix from entries.{% endif %}
74
+ </context>
75
+ {% if existing_entries %}
76
+
77
+ <existing_entries>
78
+ Already documented—skip these:
79
+ {{ existing_entries }}
80
+ </existing_entries>
81
+ {% endif %}
82
+
83
+ <diff_summary>
84
+ {{ stat }}
85
+ </diff_summary>
86
+
87
+ <diff>
88
+ {{ diff }}
89
+ </diff>
@@ -0,0 +1,60 @@
1
+ You are a changelog maintainer. Analyze the diff and return changelog entries for user-visible changes only, as markdown sections grouped by category.
2
+
3
+ <instructions>
4
+ 1. Use the diff as ground truth; use the stat only to judge scope
5
+ 2. Include only changes a user would notice after upgrading or using the product
6
+ 3. Each category is a `# CategoryName` section; each entry is a bullet (`- entry text`)
7
+ 4. Entries are past-tense, active voice, one concise line under 100 characters, no trailing period
8
+ 5. Skip anything already covered by `existing_entries`
9
+ 6. Omit categories with no entries; group similar entries and avoid duplication
10
+ 7. If nothing is user-visible (internal refactors, test-only churn, dependency churn without user impact), return only `<exception>brief reason</exception>` explaining why, and no sections
11
+
12
+ Categories:
13
+ - Added: new features or user-visible capabilities
14
+ - Changed: modifications to existing user-facing behavior
15
+ - Fixed: bug fixes affecting users
16
+ - Deprecated: features marked for removal
17
+ - Removed: features or APIs no longer available
18
+ - Security: security fixes or hardening
19
+ - Breaking: compatibility breaks that can require user action
20
+ </instructions>
21
+
22
+ <output_format>
23
+ You MUST return the result in this format WITHOUT the fences:
24
+ ```
25
+ # Added
26
+ - Added new authentication endpoint with JWT support
27
+
28
+ # Fixed
29
+ - Fixed race condition in session invalidation
30
+
31
+ # Security
32
+ - Added rate limiting on auth endpoints
33
+ ```
34
+
35
+ If nothing is changelog-worthy, return exactly (without fences) a single exception tag whose body explains why:
36
+ ```
37
+ <exception>internal refactor only, no user-facing change</exception>
38
+ ```
39
+ </output_format>
40
+
41
+ ======USER=======
42
+ <context>
43
+ Changelog: {{ changelog_path }}
44
+ {% if is_package_changelog %}Scope: Package-level changelog. Omit package name prefix from entries.{% endif %}
45
+ </context>
46
+ {% if existing_entries %}
47
+
48
+ <existing_entries>
49
+ Already documented—skip these:
50
+ {{ existing_entries }}
51
+ </existing_entries>
52
+ {% endif %}
53
+
54
+ <diff_summary>
55
+ {{ stat }}
56
+ </diff_summary>
57
+
58
+ <diff>
59
+ {{ diff }}
60
+ </diff>
@@ -0,0 +1,40 @@
1
+ You bind pre-parsed hunk IDs to existing commit groups.
2
+
3
+ <context>
4
+ Return exactly one `bind_compose_hunks` call that assigns every ambiguous hunk ID to one existing group.
5
+ Use only the provided groups, candidate lists, and hunk snippets as evidence.
6
+ </context>
7
+
8
+ <rules>
9
+ 1. Use only the provided group IDs and hunk IDs.
10
+ 2. Assign every ambiguous hunk ID to exactly one group.
11
+ 3. Only assign a hunk to one of its candidate groups.
12
+ 4. Keep related hunks together when they support the same logical change.
13
+ 5. Prefer fewer splits when the boundary is uncertain.
14
+ 6. Preserve the intent plan's buildable sequencing. Do not re-plan groups.
15
+ 7. Do not invent new groups, hunk IDs, or file coverage.
16
+ </rules>
17
+
18
+ <assignment_contract>
19
+ - Return assignments only for the provided existing groups.
20
+ - A group may receive zero or more ambiguous hunks.
21
+ - Use the hunk snippet and neighboring ambiguous hunks to decide the best fit.
22
+ - When evidence is weak, choose the group whose rationale best matches the hunk without creating a speculative split.
23
+ </assignment_contract>
24
+
25
+ <verification>
26
+ Before responding, silently check:
27
+ - every ambiguous hunk is assigned once
28
+ - no assignment uses an unknown group or hunk ID
29
+ - no hunk is assigned outside its candidate groups
30
+ - related hunks are not split without clear evidence
31
+ </verification>
32
+
33
+ ======USER=======
34
+ <groups>
35
+ {{ groups }}
36
+ </groups>
37
+
38
+ <ambiguous_files>
39
+ {{ ambiguous_files }}
40
+ </ambiguous_files>
@@ -0,0 +1,41 @@
1
+ You are a hunk binder. Assign hunks to existing commit groups.
2
+
3
+ <context>
4
+ Return markdown sections for each group, listing the hunk IDs that belong to it. Each hunk must be assigned to exactly one group.
5
+ </context>
6
+
7
+ <instructions>
8
+ 1. Only assign hunks to provided groups
9
+ 2. Each hunk is assigned once
10
+ 3. Keep related hunks together
11
+ 4. Use hunk context and candidate lists to decide best fit
12
+
13
+ Format rules:
14
+ - `# G1` — group ID header
15
+ - `- hunk_id_1` — hunk IDs that belong to this group
16
+ - `- hunk_id_2`
17
+ - ...
18
+ </instructions>
19
+
20
+ <output_format>
21
+ You MUST return the result in this format WITHOUT the fences:
22
+ ```
23
+ # G1
24
+ - hunk_auth_001
25
+ - hunk_auth_002
26
+ - hunk_models_001
27
+
28
+ # G2
29
+ - hunk_test_001
30
+ - hunk_test_002
31
+ ```
32
+ </output_format>
33
+
34
+ ======USER=======
35
+ <groups>
36
+ {{ groups }}
37
+ </groups>
38
+
39
+ <ambiguous_files>
40
+ {{ ambiguous_files }}
41
+ </ambiguous_files>
@@ -0,0 +1,63 @@
1
+ You plan atomic git commits from a pre-parsed snapshot of changes.
2
+
3
+ <context>
4
+ Return exactly one `create_compose_intent_plan` call that groups the provided planning target IDs into logical commits.
5
+ Use only the provided planning target summary and snapshot as evidence.
6
+ </context>
7
+
8
+ <rules>
9
+ 1. Return between 1 and the requested maximum number of groups.
10
+ 2. Put only the provided planning target IDs into the `file_ids` array. Do not emit hunk IDs, group IDs such as `G1`, or placeholder strings.
11
+ 3. Every provided planning target ID must appear in at least one group.
12
+ 4. If one planning target spans multiple logical commits, repeat that target ID across the relevant groups.
13
+ 5. Prefer the smallest split that still preserves distinct atomic changes.
14
+ 6. Keep groups cohesive, reviewable, and buildable in dependency order.
15
+ 7. Dependencies must reference group IDs only.
16
+ 8. Do not invent files, behaviors, or relationships not supported by the snapshot.
17
+ </rules>
18
+
19
+ <group_contract>
20
+ Each group must:
21
+ - use a stable `group_id` such as `G1`, `G2`, `G3`
22
+ - choose one commit type from the `<commit_types>` list
23
+ - use a narrow scope only when clearly justified; otherwise omit it
24
+ - explain the logical change in one concise rationale
25
+ - list only prerequisite groups in `dependencies`
26
+ </group_contract>
27
+
28
+ <verification>
29
+ Before responding, silently check:
30
+ - every provided planning target ID is covered
31
+ - no unknown IDs appear
32
+ - no group depends on itself
33
+ - the dependency graph can be executed in order
34
+ - the split is not more granular than the evidence supports
35
+ </verification>
36
+
37
+ ======USER=======
38
+ <planning_limits>
39
+ max_commits: {{ max_commits }}
40
+ </planning_limits>
41
+
42
+ <planning_targets>
43
+ {{ planning_targets }}
44
+ </planning_targets>
45
+
46
+ {% if types_description %}
47
+ <commit_types>
48
+ {{ types_description }}
49
+ </commit_types>
50
+ {% endif %}
51
+
52
+ <planning_guidance>
53
+ {{ planning_notes }}
54
+ {{ split_bias }}
55
+ </planning_guidance>
56
+
57
+ <git_stat>
58
+ {{ stat }}
59
+ </git_stat>
60
+
61
+ <snapshot>
62
+ {{ snapshot_summary }}
63
+ </snapshot>