@eldrforge/kodrdriv 1.2.13 â 1.2.16
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.
- package/dist/arguments.js +13 -4
- package/dist/arguments.js.map +1 -1
- package/dist/commands/development.js +133 -3
- package/dist/commands/development.js.map +1 -1
- package/dist/commands/publish.js +46 -98
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/release.js +12 -10
- package/dist/commands/release.js.map +1 -1
- package/dist/constants.js +5 -2
- package/dist/constants.js.map +1 -1
- package/dist/prompt/commit.js +3 -0
- package/dist/prompt/commit.js.map +1 -1
- package/dist/prompt/instructions/commit.md +87 -68
- package/dist/prompt/instructions/release.md +67 -21
- package/dist/util/git.js +135 -37
- package/dist/util/git.js.map +1 -1
- package/dist/util/openai.js +17 -2
- package/dist/util/openai.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
**đ§ Task Definition**
|
|
2
2
|
|
|
3
|
-
You are generating a Git commit message
|
|
3
|
+
You are generating a Git commit message that describes **ONLY THE CURRENT DIFF**.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## â ī¸ CRITICAL RULES - READ FIRST
|
|
8
|
+
|
|
9
|
+
1. **THE DIFF IS YOUR ONLY SOURCE OF TRUTH** - Your commit message must describe ONLY what appears in the `[Diff]` section
|
|
10
|
+
2. **IGNORE LOG CONTEXT** - Previous commits are shown for background only. DO NOT describe them, reference them, or let them influence your message
|
|
11
|
+
3. **CITE SPECIFIC FILES** - Every change you mention must reference actual files from the diff (e.g., "Remove post-publish sync logic in src/commands/publish.ts")
|
|
12
|
+
4. **NO HALLUCINATIONS** - If you mention a change, it MUST exist in the diff. Describing changes not in the diff is a critical failure
|
|
13
|
+
5. **LENGTH FOLLOWS SCOPE** - Typical commits are 3-6 lines. Very large architectural changes may warrant essay-length messages, but every line must still describe actual changes from the diff
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## đ Input Sections
|
|
18
|
+
|
|
19
|
+
* **\[User Direction]** â When present, use this to understand the user's INTENT, but your commit message must still accurately describe what's in the diff
|
|
20
|
+
* **\[User Context]** â Optional background about the user's environment
|
|
21
|
+
* **\[Diff]** â **THE ONLY SOURCE OF TRUTH** - This shows exactly what changed. Describe ONLY these changes
|
|
22
|
+
* **\[Project Files]** â Only present for new repositories with no diff
|
|
23
|
+
* **\[Recent GitHub Issues]** â Optional context for understanding motivation. Only reference issues if the diff clearly addresses them
|
|
24
|
+
* **\[Log Context]** â **IGNORE THIS** - Previous commit messages shown for background only. DO NOT describe previous commits or copy their language
|
|
11
25
|
|
|
12
26
|
---
|
|
13
27
|
|
|
@@ -15,100 +29,105 @@ You are generating a Git commit message based on the content provided below. The
|
|
|
15
29
|
|
|
16
30
|
### â
DO:
|
|
17
31
|
|
|
18
|
-
* **
|
|
19
|
-
* **
|
|
20
|
-
* **
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
- Connect **related changes** to their original requirements or bug reports
|
|
25
|
-
- **For smaller commits**: Only reference issues if directly relevant; don't force connections
|
|
26
|
-
- **For larger commits**: Use issues to explain the broader context and group related changes
|
|
27
|
-
* **FOCUS ON THE CURRENT CHANGE**: Your commit message should describe only what is happening in the current diff or project files â not previous work or future plans. For new repositories with project files, focus on describing what has been initially added.
|
|
28
|
-
* Start with a **clear, concise summary** of what was changed and why â grounded in the `User Direction` when present and informed by any `User Context`.
|
|
29
|
-
* **ALWAYS GROUP CHANGES INTO SEPARATE LINES**: Break down changes into distinct logical groups, with each group on its own line. Even for simple changes, use multiple lines when there are different types of modifications.
|
|
30
|
-
* **USE BULLET POINTS BY DEFAULT**: Format most commit messages with bullet points to clearly separate different groups of changes.
|
|
31
|
-
* **Refer to specific changes** seen in the `Diff` or specific files/components in `Project Files`, and explain why those changes matter when it's non-obvious.
|
|
32
|
-
* Keep the tone technical and direct â written for a fellow developer who will read this in six months.
|
|
32
|
+
* **Ground every statement in the diff** - Mention specific files that changed (e.g., "Add retry logic to src/api/client.ts")
|
|
33
|
+
* **Start with clear intent** - One line explaining the overall purpose
|
|
34
|
+
* **Use bullet points** - Separate distinct changes into individual bullets
|
|
35
|
+
* **Be specific** - "Remove 68 lines of post-publish sync code" not "Refactor publish flow"
|
|
36
|
+
* **Match length to scope** - Most commits are 3-6 lines. Massive architectural changes can warrant longer, detailed messages when the scope justifies it
|
|
37
|
+
* **Use technical language** - Direct, precise, no fluff
|
|
33
38
|
|
|
34
39
|
### â DO NOT:
|
|
35
40
|
|
|
36
|
-
* â **
|
|
37
|
-
* â **
|
|
38
|
-
* â
|
|
39
|
-
* â
|
|
40
|
-
* â
|
|
41
|
-
* â
|
|
42
|
-
* â
|
|
43
|
-
* â **Don't reference or describe previous commits from the log context** â focus only on the current change.
|
|
44
|
-
* â **Don't let the log context influence your commit message content** â it's background information only.
|
|
45
|
-
* â **Don't continue themes or patterns from previous commits** unless they're directly relevant to the current diff.
|
|
41
|
+
* â **NEVER describe changes not in the diff** - This is the #1 failure mode
|
|
42
|
+
* â **NEVER reference log context** - Don't describe "this continues previous work" or similar
|
|
43
|
+
* â **NEVER use vague language** - "Improve", "refactor", "enhance" without specifics
|
|
44
|
+
* â **NEVER write multi-paragraph essays** - Keep it concise
|
|
45
|
+
* â **NEVER mention test changes unless they're significant** - Focus on production code
|
|
46
|
+
* â **NEVER use markdown** - Plain text only
|
|
47
|
+
* â **NEVER begin with "This commit..."** - Just describe what changed
|
|
46
48
|
|
|
47
49
|
---
|
|
48
50
|
|
|
49
|
-
## đ OUTPUT
|
|
51
|
+
## đ OUTPUT FORMATS & EXAMPLES
|
|
50
52
|
|
|
51
|
-
### â
|
|
53
|
+
### â
GOOD: Concise with file citations (3-6 lines)
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
> Remove post-publish branch sync and version bump automation
|
|
56
|
+
>
|
|
57
|
+
> * Delete 68 lines of merge/version-bump code from src/commands/publish.ts (lines 1039-1106)
|
|
58
|
+
> * Replace with simple completion message and manual next-steps guidance
|
|
59
|
+
> * Add verbose logging to git tag search in src/util/git.ts for debugging
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
* **Bullet points** for each distinct group of changes
|
|
57
|
-
* Each bullet should represent a different logical area (files, functionality, configuration, tests, etc.)
|
|
61
|
+
**Why this is good:** Specific files, line counts, describes what actually changed
|
|
58
62
|
|
|
59
|
-
|
|
63
|
+
---
|
|
60
64
|
|
|
61
|
-
|
|
62
|
-
>
|
|
63
|
-
> * Switch from parseUser() to getUserProfile() in session.ts
|
|
64
|
-
> * Update session schema validation in auth.ts
|
|
65
|
-
> * Remove legacy parsing logic from user-utils.ts
|
|
66
|
-
> * Update related tests in session.test.ts
|
|
65
|
+
### â
GOOD: Single atomic change (1 line)
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
> Fix typo in error message for invalid credentials in src/auth/validator.ts
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
>
|
|
72
|
-
> * Increase session timeout from 30min to 2hrs in config.ts (fixes #145)
|
|
73
|
-
> * Add automatic token refresh logic in auth-service.ts (fixes #167)
|
|
74
|
-
> * Update error handling for expired sessions in middleware.ts
|
|
75
|
-
> * Add tests for extended session scenarios in auth.test.ts
|
|
69
|
+
**Why this is good:** One file, one change, specific
|
|
76
70
|
|
|
77
71
|
---
|
|
78
72
|
|
|
79
|
-
### â
|
|
80
|
-
|
|
81
|
-
**ONLY use a single line when the change is truly atomic** - affecting one function in one file with one clear purpose:
|
|
73
|
+
### â
GOOD: Multiple related changes (4-7 lines)
|
|
82
74
|
|
|
83
|
-
|
|
75
|
+
> Add retry logic for API timeout errors
|
|
76
|
+
>
|
|
77
|
+
> * Implement exponential backoff in src/api/client.ts
|
|
78
|
+
> * Add max retry configuration to src/config/api.ts
|
|
79
|
+
> * Update error handling in src/api/error-handler.ts to detect retryable errors
|
|
80
|
+
> * Add retry tests in tests/api/client.test.ts
|
|
84
81
|
|
|
85
|
-
|
|
82
|
+
**Why this is good:** Grounded in actual files, specific changes, concise
|
|
86
83
|
|
|
87
84
|
---
|
|
88
85
|
|
|
89
|
-
###
|
|
86
|
+
### â BAD: Hallucinated changes (DO NOT DO THIS)
|
|
87
|
+
|
|
88
|
+
> Centralize ref-detection and streamline publish flow
|
|
89
|
+
>
|
|
90
|
+
> * Move to single ref-detection approach and stop passing from/to into Log.create()
|
|
91
|
+
> * Replace ad-hoc fromRef/toRef handling in src/commands/release.ts
|
|
92
|
+
> * Scale diff context: DEFAULT_MAX_DIFF_BYTES now 20480
|
|
93
|
+
> * Update tests to mock new git boundary
|
|
94
|
+
> * Update docs/public/commands/publish.md
|
|
90
95
|
|
|
91
|
-
|
|
96
|
+
**Why this is terrible:** These changes aren't in the diff! The LLM is describing previous commits from log context instead of the actual diff. This is the #1 failure mode to avoid.
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
* One or two **detail paragraphs** focusing on key aspects or trade-offs
|
|
95
|
-
* **Bullet points** to call out specific files, tools, or changes
|
|
98
|
+
---
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
### â BAD: Verbose multi-paragraph essay (DO NOT DO THIS)
|
|
98
101
|
|
|
99
102
|
> Reorganize pipeline logic to improve readability and make phase execution more testable. This is part of ongoing work to modularize transition handling.
|
|
100
103
|
>
|
|
101
104
|
> The main change separates phase node execution into its own module, reduces reliance on shared state, and simplifies test construction. Existing functionality remains unchanged, but internal structure is now better aligned with future transition plugin support.
|
|
102
105
|
>
|
|
106
|
+
> This commit represents a significant cleanup of the execution flow and provides a safer foundation for future operations.
|
|
107
|
+
>
|
|
103
108
|
> * Extract executePhaseNode() from pipeline.ts
|
|
104
109
|
> * Add phase-runner.ts with dedicated error handling
|
|
105
|
-
>
|
|
106
|
-
|
|
110
|
+
> ...
|
|
111
|
+
|
|
112
|
+
**Why this is terrible:** Way too verbose (could be 3 lines), fluffy language, unnecessary context paragraphs
|
|
107
113
|
|
|
108
114
|
---
|
|
109
115
|
|
|
110
|
-
|
|
116
|
+
### â BAD: Vague without file citations (DO NOT DO THIS)
|
|
117
|
+
|
|
118
|
+
> Improve error handling and refactor configuration logic
|
|
119
|
+
|
|
120
|
+
**Why this is terrible:** No specific files, vague verbs like "improve" and "refactor", no details
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## đ¯ Length Guidelines
|
|
125
|
+
|
|
126
|
+
* **Single change:** 1 line
|
|
127
|
+
* **Typical commit:** 3-6 lines (summary + 2-5 bullets)
|
|
128
|
+
* **Large commit:** 6-15 lines
|
|
129
|
+
* **Major architectural change:** Essay-length if warranted (rare but valid)
|
|
111
130
|
|
|
112
|
-
**
|
|
131
|
+
**There is no hard upper limit.** The constraint is not length - it's **accuracy**. Every line must describe actual changes from the diff.
|
|
113
132
|
|
|
114
|
-
|
|
133
|
+
Write as much as you need to accurately describe the changes, but no more. A 50-line commit message is fine if the diff touches 30 files and restructures core systems. A 6-line commit message that describes changes not in the diff is a critical failure, regardless of its brevity.
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
## â ī¸ CRITICAL RULES - READ FIRST
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
1. **LOG MESSAGES ARE YOUR SOURCE OF TRUTH** - Every change you describe must come from actual commit messages in the `[Log Context]` section or issues in `[Resolved Issues from Milestone]`
|
|
4
|
+
2. **NO HALLUCINATIONS** - Do not invent features, fixes, or changes that aren't explicitly mentioned in the log messages or milestone issues
|
|
5
|
+
3. **CITE ACTUAL COMMITS** - When describing changes, refer to what's in the actual commit messages, not what you think should be there
|
|
6
|
+
4. **USE RELEASE FOCUS FOR FRAMING** - The `[Release Focus]` guides how you frame and emphasize changes, but doesn't add new changes not in the logs
|
|
7
|
+
5. **LENGTH FOLLOWS SCOPE** - Small releases get concise notes. Large releases deserve comprehensive documentation. Match the actual scope of changes in the log
|
|
4
8
|
|
|
5
|
-
|
|
9
|
+
---
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
## Your Task
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
Write release notes by reading all commit messages in `[Log Context]` and milestone issues in `[Resolved Issues from Milestone]`. Every change you mention must be traceable to an actual commit message or resolved issue.
|
|
10
14
|
|
|
11
15
|
### Output Format
|
|
12
16
|
|
|
@@ -91,19 +95,19 @@ Create release notes that:
|
|
|
91
95
|
|
|
92
96
|
3. **Use clear, factual bullet points** under each section. Briefly describe what changed and why it's relevant â **write like a developer documenting changes, not like marketing copy**.
|
|
93
97
|
|
|
98
|
+
**CRITICAL**: Every bullet point must be traceable to actual commit messages in `[Log Context]` or issues in `[Resolved Issues from Milestone]`. If a change isn't in the log, don't mention it.
|
|
99
|
+
|
|
94
100
|
**For large releases**: Provide detailed bullet points that explain:
|
|
95
|
-
- What specifically changed
|
|
101
|
+
- What specifically changed (cite actual commit messages)
|
|
96
102
|
- Why the change was made (if evident from commit messages or issue descriptions)
|
|
97
|
-
- Impact on users or developers
|
|
98
|
-
- Related files or components affected (when
|
|
103
|
+
- Impact on users or developers (based on commit/issue context)
|
|
104
|
+
- Related files or components affected (when mentioned in commits)
|
|
99
105
|
|
|
100
|
-
|
|
101
|
-
*
|
|
102
|
-
* "
|
|
103
|
-
* "
|
|
104
|
-
*
|
|
105
|
-
* "streamlined workflow"
|
|
106
|
-
* "enhanced user experience"
|
|
106
|
+
**DO NOT**:
|
|
107
|
+
* Invent features not mentioned in commits
|
|
108
|
+
* Describe changes that "should" be there but aren't in the log
|
|
109
|
+
* Use vague or exaggerated marketing terms like "awesome new feature", "significant boost", "revolutionary update", "streamlined workflow", "enhanced user experience"
|
|
110
|
+
* Group unrelated commits under theme names that aren't in the actual commits
|
|
107
111
|
|
|
108
112
|
4. **Keep your tone technical, neutral, and useful.** It's okay to include references to:
|
|
109
113
|
|
|
@@ -121,22 +125,64 @@ Create release notes that:
|
|
|
121
125
|
|
|
122
126
|
---
|
|
123
127
|
|
|
128
|
+
## Anti-Examples: What NOT to Do
|
|
129
|
+
|
|
130
|
+
### â BAD: Hallucinated Changes
|
|
131
|
+
|
|
132
|
+
**Problem**: The release notes describe features that aren't in any commit message:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"title": "Major Performance Overhaul and API Redesign",
|
|
137
|
+
"body": "**Performance Improvements**\\n\\n* Reduced API response times by 60% through query optimization\\n* Implemented connection pooling for database efficiency\\n* Added Redis caching layer for frequently accessed data\\n\\n**API Redesign**\\n\\n* Completely redesigned REST API with versioning support\\n* Migrated all endpoints to new authentication system"
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Why it's terrible**: None of these changes appear in the commit log. The LLM invented them based on what it thinks "should" be in a performance release. This is a critical failure even if the notes sound good.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### â BAD: Vague Marketing Fluff
|
|
146
|
+
|
|
147
|
+
**Problem**: Generic marketing language instead of specific commit-based changes:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"title": "Enhanced User Experience and Streamlined Workflows",
|
|
152
|
+
"body": "This exciting release brings revolutionary improvements to the user experience! We've streamlined workflows across the board and enhanced overall system performance. Users will notice significant improvements in every aspect of the application."
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Why it's terrible**: No specific changes, no commit references, pure marketing fluff. Completely useless to developers.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
124
160
|
## Output Format Examples
|
|
125
161
|
|
|
126
|
-
###
|
|
162
|
+
### â
GOOD: Grounded in Actual Commits
|
|
163
|
+
|
|
164
|
+
**Scenario**: Log contains commits about removing post-publish sync, adding verbose logging, and fixing a config bug
|
|
127
165
|
|
|
128
166
|
```json
|
|
129
167
|
{
|
|
130
|
-
"title": "
|
|
131
|
-
"body": "
|
|
168
|
+
"title": "Simplify publish flow and improve git tag debugging",
|
|
169
|
+
"body": "**Workflow Changes**\\n\\n* Remove automatic branch sync and version bump from publish flow - users now manually run `kodrdriv development` to continue work after publish\\n* Simplify publish completion to show next steps instead of auto-syncing\\n\\n**Debugging Improvements**\\n\\n* Add extensive logging to git tag detection in `getDefaultFromRef()` to diagnose tag search issues\\n* Add emoji indicators and structured output for tag search process\\n\\n**Bug Fixes**\\n\\n* Fix config validation error when optional field was missing"
|
|
132
170
|
}
|
|
133
171
|
```
|
|
134
172
|
|
|
135
|
-
|
|
173
|
+
**Why it's good**: Every bullet point traces to an actual commit. Specific file references. No invented features.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
### â
GOOD: Large Release with Detail
|
|
178
|
+
|
|
179
|
+
**Scenario**: 30 commits touching configuration system, tests, docs, and CLI
|
|
136
180
|
|
|
137
181
|
```json
|
|
138
182
|
{
|
|
139
|
-
"title": "
|
|
140
|
-
"body": "This release
|
|
183
|
+
"title": "Configuration System Overhaul and Testing Migration",
|
|
184
|
+
"body": "This release modernizes the configuration system and migrates the test suite based on accumulated technical debt and developer feedback.\\n\\n**Configuration System Changes**\\n\\n* Unify vite.config.ts and webpack.config.js into single environment-aware module\\n* Add support for .env.defaults with proper precedence handling\\n* Implement config validation with detailed error messages\\n* Reduce tsconfig.json nesting depth for readability\\n\\n**Testing Infrastructure**\\n\\n* Migrate test suite from Jest to Vitest for better ES module support\\n* Add integration tests for configuration system\\n* Implement coverage reporting with branch and function metrics\\n\\n**Bug Fixes**\\n\\n* Fix crash in config loader when optional fields undefined\\n* Resolve Windows build failure due to missing path escaping\\n* Fix race condition in parallel test execution\\n\\n**Breaking Changes**\\n\\n* Remove support for legacy .env.local.js files\\n* Change default output directory from dist/ to build/\\n* Require Node.js 18.0.0 or higher\\n\\n**Documentation**\\n\\n* Rewrite setup instructions in README.md for new config process\\n* Add migration guide for users upgrading from previous versions"
|
|
141
185
|
}
|
|
142
186
|
```
|
|
187
|
+
|
|
188
|
+
**Why it's good**: Comprehensive coverage of a large release, but every change is grounded in actual commits. No fluff, just facts.
|
package/dist/util/git.js
CHANGED
|
@@ -56,59 +56,78 @@ import { safeJsonParse, validatePackageJson } from './validation.js';
|
|
|
56
56
|
* Returns the highest version tag that is less than the current version.
|
|
57
57
|
*
|
|
58
58
|
* @param currentVersion The current version (e.g., "1.2.3", "2.0.0")
|
|
59
|
+
* @param tagPattern The pattern to match tags (e.g., "v*", "working/v*")
|
|
59
60
|
* @returns The previous release tag or null if none found
|
|
60
|
-
*/ const findPreviousReleaseTag = async (currentVersion)=>{
|
|
61
|
+
*/ const findPreviousReleaseTag = async (currentVersion, tagPattern = 'v*')=>{
|
|
61
62
|
const logger = getLogger();
|
|
62
63
|
try {
|
|
63
64
|
// Parse current version first to validate it
|
|
64
65
|
const currentSemver = semver.parse(currentVersion);
|
|
65
66
|
if (!currentSemver) {
|
|
66
|
-
logger.
|
|
67
|
+
logger.warn(`â Invalid version format: ${currentVersion}`);
|
|
67
68
|
return null;
|
|
68
69
|
}
|
|
69
|
-
logger.
|
|
70
|
+
logger.info(`đ findPreviousReleaseTag: Looking for tags matching "${tagPattern}" < ${currentVersion}`);
|
|
70
71
|
// Get all tags - try sorted first, fallback to unsorted
|
|
71
72
|
let tags;
|
|
72
73
|
try {
|
|
74
|
+
logger.info(` Running: git tag -l "${tagPattern}" --sort=-version:refname`);
|
|
73
75
|
const { stdout } = await runSecure('git', [
|
|
74
76
|
'tag',
|
|
77
|
+
'-l',
|
|
78
|
+
tagPattern,
|
|
75
79
|
'--sort=-version:refname'
|
|
76
80
|
]);
|
|
77
81
|
tags = stdout.trim().split('\n').filter((tag)=>tag.length > 0);
|
|
78
|
-
|
|
82
|
+
logger.info(` â
Found ${tags.length} tags matching pattern "${tagPattern}"`);
|
|
83
|
+
if (tags.length > 0) {
|
|
84
|
+
logger.info(` đ Tags (newest first): ${tags.slice(0, 15).join(', ')}${tags.length > 15 ? ` ... (${tags.length - 15} more)` : ''}`);
|
|
85
|
+
}
|
|
86
|
+
} catch (sortError) {
|
|
79
87
|
// Fallback for older git versions that don't support --sort
|
|
80
|
-
logger.
|
|
88
|
+
logger.info(` â ī¸ Git tag --sort failed: ${sortError.message}`);
|
|
89
|
+
logger.info(` Falling back to manual sorting...`);
|
|
81
90
|
const { stdout } = await runSecure('git', [
|
|
82
|
-
'tag'
|
|
91
|
+
'tag',
|
|
92
|
+
'-l',
|
|
93
|
+
tagPattern
|
|
83
94
|
]);
|
|
84
95
|
tags = stdout.trim().split('\n').filter((tag)=>tag.length > 0);
|
|
96
|
+
logger.info(` Found ${tags.length} tags (unsorted) matching pattern "${tagPattern}"`);
|
|
85
97
|
// Manual semantic version sorting
|
|
86
98
|
tags.sort((a, b)=>{
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
if (!aSemver) return
|
|
93
|
-
|
|
94
|
-
// Sort in descending order (newest first)
|
|
95
|
-
return semver.compare(bSemver, aSemver);
|
|
99
|
+
const aMatch = a.match(/v?(\d+\.\d+\.\d+.*?)$/);
|
|
100
|
+
const bMatch = b.match(/v?(\d+\.\d+\.\d+.*?)$/);
|
|
101
|
+
if (!aMatch || !bMatch) return 0;
|
|
102
|
+
const aSemver = semver.parse(aMatch[1]);
|
|
103
|
+
const bSemver = semver.parse(bMatch[1]);
|
|
104
|
+
if (!aSemver || !bSemver) return 0;
|
|
105
|
+
return semver.rcompare(aSemver, bSemver);
|
|
96
106
|
});
|
|
107
|
+
logger.info(` â
Sorted ${tags.length} tags manually`);
|
|
97
108
|
}
|
|
98
109
|
if (tags.length === 0) {
|
|
99
|
-
logger.
|
|
110
|
+
logger.warn('');
|
|
111
|
+
logger.warn(`â NO TAGS FOUND matching pattern "${tagPattern}"`);
|
|
112
|
+
logger.warn(` To verify, run: git tag -l '${tagPattern}'`);
|
|
113
|
+
logger.warn('');
|
|
100
114
|
return null;
|
|
101
115
|
}
|
|
102
|
-
logger.
|
|
116
|
+
logger.info(` đŦ Processing ${tags.length} tags to find the highest version < ${currentVersion}...`);
|
|
103
117
|
// Find the highest version that is less than the current version
|
|
104
118
|
let previousTag = null;
|
|
105
119
|
let previousVersion = null;
|
|
106
120
|
let validTags = 0;
|
|
107
121
|
let skippedTags = 0;
|
|
108
122
|
for (const tag of tags){
|
|
109
|
-
//
|
|
110
|
-
const
|
|
111
|
-
|
|
123
|
+
// Extract version from tag - handle "v1.2.13", "1.2.13", and "working/v1.2.13"
|
|
124
|
+
const versionMatch = tag.match(/v?(\d+\.\d+\.\d+.*?)$/);
|
|
125
|
+
if (!versionMatch) {
|
|
126
|
+
logger.debug(` âī¸ Skipping tag "${tag}" (doesn't match version pattern)`);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const versionString = versionMatch[1];
|
|
130
|
+
const tagSemver = semver.parse(versionString);
|
|
112
131
|
if (tagSemver) {
|
|
113
132
|
validTags++;
|
|
114
133
|
// Check if this tag version is less than current version
|
|
@@ -116,24 +135,35 @@ import { safeJsonParse, validatePackageJson } from './validation.js';
|
|
|
116
135
|
// If we don't have a previous version yet, or this one is higher than our current previous
|
|
117
136
|
if (!previousVersion || semver.gt(tagSemver, previousVersion)) {
|
|
118
137
|
previousVersion = tagSemver;
|
|
119
|
-
previousTag = tag; // Keep the original tag format
|
|
120
|
-
logger.
|
|
138
|
+
previousTag = tag; // Keep the original tag format
|
|
139
|
+
logger.info(` â
New best candidate: ${tag} (${versionString} < ${currentVersion})`);
|
|
140
|
+
} else {
|
|
141
|
+
logger.debug(` âī¸ ${tag} (${versionString}) is < current but not better than ${previousTag}`);
|
|
121
142
|
}
|
|
122
143
|
} else {
|
|
123
144
|
skippedTags++;
|
|
145
|
+
logger.debug(` âī¸ ${tag} (${versionString}) >= current (${currentVersion}), skipping`);
|
|
124
146
|
}
|
|
125
147
|
}
|
|
126
148
|
}
|
|
127
|
-
logger.
|
|
149
|
+
logger.info('');
|
|
150
|
+
logger.info(` đ Tag analysis results:`);
|
|
151
|
+
logger.info(` - Total tags examined: ${tags.length}`);
|
|
152
|
+
logger.info(` - Valid semver tags: ${validTags}`);
|
|
153
|
+
logger.info(` - Tags >= current version (skipped): ${skippedTags}`);
|
|
154
|
+
logger.info(` - Best match: ${previousTag || 'none'}`);
|
|
155
|
+
logger.info('');
|
|
128
156
|
if (previousTag) {
|
|
129
|
-
logger.info(
|
|
130
|
-
|
|
131
|
-
logger.
|
|
132
|
-
|
|
133
|
-
logger.debug('All existing tags are greater than or equal to current version (likely first release)');
|
|
134
|
-
}
|
|
157
|
+
logger.info(`â
SUCCESS: Found previous tag: ${previousTag}`);
|
|
158
|
+
logger.info(` Version comparison: ${previousVersion === null || previousVersion === void 0 ? void 0 : previousVersion.version} < ${currentVersion}`);
|
|
159
|
+
logger.info('');
|
|
160
|
+
return previousTag;
|
|
135
161
|
}
|
|
136
|
-
|
|
162
|
+
logger.warn(`â FAILED: No previous tag found for version ${currentVersion}`);
|
|
163
|
+
logger.warn(` Pattern searched: "${tagPattern}"`);
|
|
164
|
+
logger.warn(` Reason: All ${validTags} valid tags were >= ${currentVersion}`);
|
|
165
|
+
logger.warn('');
|
|
166
|
+
return null;
|
|
137
167
|
} catch (error) {
|
|
138
168
|
logger.debug(`Error finding previous release tag: ${error.message}`);
|
|
139
169
|
return null;
|
|
@@ -181,21 +211,89 @@ import { safeJsonParse, validatePackageJson } from './validation.js';
|
|
|
181
211
|
* Gets a reliable default for the --from parameter by trying multiple fallbacks
|
|
182
212
|
*
|
|
183
213
|
* Tries in order:
|
|
184
|
-
* 1. Previous
|
|
185
|
-
* 2.
|
|
186
|
-
* 3.
|
|
187
|
-
* 4.
|
|
188
|
-
* 5. origin/
|
|
214
|
+
* 1. Previous working branch tag (if on working branch)
|
|
215
|
+
* 2. Previous release tag (if current version can be determined)
|
|
216
|
+
* 3. main (local main branch - typical release comparison base)
|
|
217
|
+
* 4. master (local master branch - legacy default)
|
|
218
|
+
* 5. origin/main (remote main branch fallback)
|
|
219
|
+
* 6. origin/master (remote master branch fallback)
|
|
189
220
|
*
|
|
190
221
|
* @param forceMainBranch If true, skip tag detection and use main branch
|
|
222
|
+
* @param currentBranch Current branch name for branch-aware tag detection
|
|
191
223
|
* @returns A valid git reference to use as the default from parameter
|
|
192
224
|
* @throws Error if no valid reference can be found
|
|
193
|
-
*/ const getDefaultFromRef = async (forceMainBranch = false)=>{
|
|
225
|
+
*/ const getDefaultFromRef = async (forceMainBranch = false, currentBranch)=>{
|
|
194
226
|
const logger = getLogger();
|
|
227
|
+
logger.info('');
|
|
228
|
+
logger.info('âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ');
|
|
229
|
+
logger.info('đ DETECTING DEFAULT --from REFERENCE FOR RELEASE NOTES');
|
|
230
|
+
logger.info('âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ');
|
|
231
|
+
logger.info(`đ Input parameters:`);
|
|
232
|
+
logger.info(` - forceMainBranch: ${forceMainBranch}`);
|
|
233
|
+
logger.info(` - currentBranch: "${currentBranch}"`);
|
|
234
|
+
logger.info('');
|
|
195
235
|
// If forced to use main branch, skip tag detection
|
|
196
236
|
if (forceMainBranch) {
|
|
197
|
-
logger.
|
|
237
|
+
logger.info('⥠Forced to use main branch, skipping tag detection');
|
|
198
238
|
} else {
|
|
239
|
+
// If on working branch, look for working branch tags first
|
|
240
|
+
logger.info(`đ¯ Branch check: currentBranch="${currentBranch}", isWorking=${currentBranch === 'working'}`);
|
|
241
|
+
if (currentBranch && currentBranch === 'working') {
|
|
242
|
+
logger.info('');
|
|
243
|
+
logger.info('đ DETECTED WORKING BRANCH - Searching for working branch tags...');
|
|
244
|
+
logger.info('âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ');
|
|
245
|
+
try {
|
|
246
|
+
const currentVersion = await getCurrentVersion();
|
|
247
|
+
logger.info(`đĻ Current version from package.json: ${currentVersion}`);
|
|
248
|
+
if (currentVersion) {
|
|
249
|
+
logger.info(`đ Searching for tags matching pattern: "working/v*"`);
|
|
250
|
+
logger.info(` (Looking for tags < ${currentVersion})`);
|
|
251
|
+
logger.info('');
|
|
252
|
+
const previousTag = await findPreviousReleaseTag(currentVersion, 'working/v*');
|
|
253
|
+
logger.info(`đ¯ findPreviousReleaseTag result: ${previousTag || 'null (no tag found)'}`);
|
|
254
|
+
if (previousTag) {
|
|
255
|
+
logger.info(`đŦ Validating tag reference: "${previousTag}"`);
|
|
256
|
+
const isValid = await isValidGitRef(previousTag);
|
|
257
|
+
logger.info(` Tag is valid git ref: ${isValid}`);
|
|
258
|
+
if (isValid) {
|
|
259
|
+
logger.info('');
|
|
260
|
+
logger.info(`â
SUCCESS: Using previous working branch tag '${previousTag}'`);
|
|
261
|
+
logger.info(` This shows commits added since the last release`);
|
|
262
|
+
logger.info('âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ');
|
|
263
|
+
logger.info('');
|
|
264
|
+
return previousTag;
|
|
265
|
+
} else {
|
|
266
|
+
logger.warn('');
|
|
267
|
+
logger.warn(`â ī¸ VALIDATION FAILED: Tag "${previousTag}" exists but is not a valid git reference`);
|
|
268
|
+
logger.warn(` This should not happen - the tag might be corrupted`);
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
logger.warn('');
|
|
272
|
+
logger.warn('â NO WORKING BRANCH TAG FOUND matching pattern "working/v*"');
|
|
273
|
+
logger.warn(` Current version: ${currentVersion}`);
|
|
274
|
+
logger.warn(' đĄ To create working branch tags for past releases, run:');
|
|
275
|
+
logger.warn(' kodrdriv development --create-retroactive-tags');
|
|
276
|
+
logger.warn('');
|
|
277
|
+
logger.warn(' Falling back to regular tag search...');
|
|
278
|
+
}
|
|
279
|
+
} else {
|
|
280
|
+
logger.warn('');
|
|
281
|
+
logger.warn('â CANNOT READ VERSION from package.json');
|
|
282
|
+
logger.warn(' Cannot search for working branch tags without current version');
|
|
283
|
+
}
|
|
284
|
+
} catch (error) {
|
|
285
|
+
logger.warn('');
|
|
286
|
+
logger.warn(`â ERROR while searching for working branch tag: ${error.message}`);
|
|
287
|
+
logger.debug(`Full error stack: ${error.stack}`);
|
|
288
|
+
logger.warn(' Falling back to regular tag search...');
|
|
289
|
+
}
|
|
290
|
+
logger.info('âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ');
|
|
291
|
+
logger.info('');
|
|
292
|
+
} else {
|
|
293
|
+
logger.info(`âšī¸ Not on "working" branch - skipping working tag search`);
|
|
294
|
+
logger.info(` (Only search for working/v* tags when on working branch)`);
|
|
295
|
+
logger.info('');
|
|
296
|
+
}
|
|
199
297
|
// First, try to find the previous release tag
|
|
200
298
|
try {
|
|
201
299
|
const currentVersion = await getCurrentVersion();
|