claude-code-orchestrator-kit 1.1.0 → 1.2.1

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.
@@ -72,7 +72,36 @@ When invoked, you must follow these steps systematically:
72
72
  ```bash
73
73
  pnpm outdated --json || npm outdated --json
74
74
  ```
75
- 6. Categorize by update type:
75
+
76
+ 6. **CRITICAL: Filter Unstable Versions**
77
+
78
+ The `outdated` command shows the "latest" tag from npm, which may include unstable pre-release versions. You MUST filter these out:
79
+
80
+ **Unstable version patterns to EXCLUDE**:
81
+ - `alpha` (e.g., `2.0.0-alpha.1`)
82
+ - `beta` (e.g., `2.0.0-beta.3`)
83
+ - `rc` (e.g., `2.0.0-rc.1`)
84
+ - `canary` (e.g., `2.0.0-canary.123`)
85
+ - `next` (e.g., `2.0.0-next.5`)
86
+ - `experimental` (e.g., `2.0.0-experimental.0`)
87
+ - `dev` (e.g., `2.0.0-dev.1`)
88
+ - `preview` (e.g., `2.0.0-preview.2`)
89
+ - `nightly` (e.g., `2.0.0-nightly.20250101`)
90
+
91
+ **For each package with unstable "latest" version**:
92
+ ```bash
93
+ # Get all available versions and find latest stable
94
+ npm view package-name versions --json
95
+ ```
96
+ Then select the highest version WITHOUT prerelease suffix.
97
+
98
+ **Example**:
99
+ - `pnpm outdated` shows: `react` latest = `19.0.0-rc.1`
100
+ - Run: `npm view react versions --json`
101
+ - Find latest stable: `18.3.1` (no prerelease suffix)
102
+ - Report `18.3.1` as target version, NOT `19.0.0-rc.1`
103
+
104
+ 7. Categorize by update type:
76
105
  - **Critical**: Security fixes (from audit)
77
106
  - **High**: Major version updates with breaking changes
78
107
  - **Medium**: Minor version updates (new features)
@@ -200,12 +229,13 @@ pnpm update lodash@^4.17.21
200
229
 
201
230
  #### 3. Major Version Update - react@17.0.2
202
231
 
203
- **Category**: Outdated Package
204
- **Priority**: high
205
- **Package**: react
206
- **Current Version**: 17.0.2
207
- **Latest Version**: 18.2.0
208
- **Update Type**: major
232
+ **Category**: Outdated Package
233
+ **Priority**: high
234
+ **Package**: react
235
+ **Current Version**: 17.0.2
236
+ **Latest Stable Version**: 18.3.1
237
+ **Update Type**: major
238
+ **Note**: Unstable versions (e.g., 19.0.0-rc.1) were excluded
209
239
 
210
240
  **Analysis**:
211
241
  - React 18 includes new features:
@@ -228,12 +258,12 @@ Requires manual migration - create separate task
228
258
 
229
259
  #### 4. Minor Update - @types/node@16.11.7
230
260
 
231
- **Category**: Outdated Package
232
- **Priority**: medium
233
- **Package**: @types/node
234
- **Current Version**: 16.11.7
235
- **Latest Version**: 16.18.0
236
- **Update Type**: minor
261
+ **Category**: Outdated Package
262
+ **Priority**: medium
263
+ **Package**: @types/node
264
+ **Current Version**: 16.11.7
265
+ **Latest Stable Version**: 16.18.0
266
+ **Update Type**: minor
237
267
 
238
268
  **Suggested Fix**:
239
269
  ```bash
@@ -68,6 +68,14 @@ When invoked, you must follow these steps:
68
68
  - Complete validation before next package
69
69
  - If validation fails, rollback immediately
70
70
 
71
+ **Version Stability Check**:
72
+ Before updating, verify target version is stable (no prerelease suffix):
73
+ ```bash
74
+ # If target version looks unstable (alpha, beta, rc, canary, next, etc.)
75
+ npm view package-name versions --json
76
+ # Select highest version WITHOUT prerelease suffix
77
+ ```
78
+
71
79
  5. **Update Categories**
72
80
 
73
81
  ### A. Security Fixes (Critical/High Priority)
@@ -399,6 +407,7 @@ When invoked, you must follow these steps:
399
407
  4. **Rollback on ANY failure** - restore backups immediately
400
408
  5. **Check migration guides** - for ALL major version updates
401
409
  6. **Document manual items** - don't skip difficult updates silently
410
+ 7. **STABLE VERSIONS ONLY** - Never update to pre-release versions (alpha, beta, rc, canary, next, experimental, dev, preview, nightly). If target version is unstable, find latest stable version instead
402
411
 
403
412
  ### Rollback Protocol
404
413
 
@@ -58,16 +58,22 @@ You **MUST** consider the user input before proceeding (if not empty).
58
58
 
59
59
  4. **PLANNING PHASE** (Execute Before Implementation):
60
60
  - Review all tasks and classify execution model (parallel vs sequential)
61
- - **Subagent Assignment** (Phase 0):
62
- * [EXECUTOR: MAIN] - ONLY for trivial tasks (1-2 line fixes, simple imports, single dependency install)
63
- * For complex tasks: thoroughly examine existing subagents, assign only if 100% match
64
- * If no 100% match: assign FUTURE agent name (to be created) - `[EXECUTOR: future-agent-name]`
65
- * After all assignments: if FUTURE agents exist, launch N meta-agent-v3 calls in single message
61
+ - **Step 1: Task Analysis**:
62
+ * Analyze all tasks and identify required agent capabilities
63
+ * Determine which tasks need MAIN (trivial only), existing agents, or new agents
64
+ * Create list of missing agent types with specifications
65
+ - **Step 2: Agent Creation** (if needed):
66
+ * Launch N meta-agent-v3 calls in single message (1 call per missing agent)
66
67
  * After agent creation: ask user to restart claude-code
67
- - Annotate tasks with `[EXECUTOR: name]` and `[SEQUENTIAL]`/`[PARALLEL-GROUP-X]`
68
- - Handle research tasks:
69
- * Simple: solve with agent tools (Grep, Read, WebSearch, Context7, Supabase docs)
70
- * Complex: create research prompt in research/, wait for user deepresearch, then incorporate results
68
+ * After restart: verify new agents exist before proceeding
69
+ - **Step 3: Executor Assignment**:
70
+ * [EXECUTOR: MAIN] - ONLY for trivial tasks (1-2 line fixes, simple imports, single dependency install)
71
+ * [EXECUTOR: existing-agent] - ONLY if 100% capability match after thorough examination
72
+ * [EXECUTOR: specific-agent-name] - For all other tasks using existing or newly created agents
73
+ * Annotate all tasks with `[EXECUTOR: name]` and `[SEQUENTIAL]`/`[PARALLEL-GROUP-X]`
74
+ - **Step 4: Research Resolution**:
75
+ * Simple research: solve with agent tools (Grep, Read, WebSearch, Context7, Supabase docs)
76
+ * Complex research: create research prompt in research/, wait for user deepresearch, incorporate results
71
77
  - Output: Updated tasks.md with executor annotations
72
78
  - **Atomicity Rule (CRITICAL)**: 1 Task = 1 Agent Invocation
73
79
  * Never give multiple tasks to one agent in single run
@@ -60,9 +60,10 @@ The tasks.md should be immediately executable - each task must be specific enoug
60
60
  - **Complex**: Create research prompt in research/ → wait for deepresearch → incorporate
61
61
 
62
62
  **Planning Phase**: After generating tasks, Phase 0: Planning will be added automatically by the template. This phase includes:
63
- - **P001**: Executor assignment (MAIN for trivial only, existing if 100% match, FUTURE otherwise)
64
- - **P002**: Research resolution (simple vs complex)
65
- - **P003**: FUTURE agent creation via meta-agent-v3 in single message, then ask restart
63
+ - **P001**: Task analysis (identify required agent types and capabilities)
64
+ - **P002**: Agent creation via meta-agent-v3 in single message, then ask restart
65
+ - **P003**: Executor assignment (MAIN for trivial only, existing if 100% match, specific agents otherwise)
66
+ - **P004**: Research resolution (simple: solve now, complex: create prompts)
66
67
 
67
68
  ## Task Generation Rules
68
69
 
@@ -6,12 +6,24 @@
6
6
  # Features:
7
7
  # - Auto-syncs package.json versions with latest git tag (prevents version conflicts)
8
8
  # - Auto-detects version bump from conventional commits
9
- # - Generates CHANGELOG.md entries
9
+ # - Generates CHANGELOG.md entries with Keep a Changelog format
10
+ # - Supports security, deprecated, and removed categories
11
+ # - Safe rollback with file backups (no data loss on errors)
10
12
  # - Rollback support for failed releases
11
13
  #
12
14
  # Usage: ./release.sh [patch|minor|major] [--yes]
13
15
  # Leave empty for auto-detection from conventional commits
14
16
  # --yes: Skip confirmation prompt (for automation)
17
+ #
18
+ # Supported conventional commit types:
19
+ # security: → Security section (patch version)
20
+ # feat: → Added section (minor version)
21
+ # fix: → Fixed section (patch version)
22
+ # deprecate: → Deprecated section
23
+ # remove: → Removed section
24
+ # refactor: → Changed section
25
+ # perf: → Changed section
26
+ # type!: → Breaking changes (major version)
15
27
 
16
28
  set -euo pipefail
17
29
 
@@ -30,8 +42,8 @@ readonly NC='\033[0m' # No Color
30
42
  # State tracking for rollback
31
43
  CREATED_COMMIT=""
32
44
  CREATED_TAG=""
33
- STASH_CREATED=""
34
45
  declare -a MODIFIED_FILES=()
46
+ declare -a BACKUP_FILES=() # Track backup files for safe rollback
35
47
 
36
48
  # Commit categorization arrays
37
49
  declare -a ALL_COMMITS=()
@@ -40,6 +52,9 @@ declare -a FIXES=()
40
52
  declare -a BREAKING_CHANGES=()
41
53
  declare -a REFACTORS=()
42
54
  declare -a PERF=()
55
+ declare -a SECURITY_FIXES=() # Security vulnerability fixes
56
+ declare -a DEPRECATIONS=() # Deprecated features
57
+ declare -a REMOVALS=() # Removed features
43
58
  declare -a OTHER_CHANGES=()
44
59
 
45
60
  # === UTILITY FUNCTIONS ===
@@ -60,6 +75,53 @@ log_error() {
60
75
  echo -e "${RED}❌ $*${NC}" >&2
61
76
  }
62
77
 
78
+ # === BACKUP AND RESTORE ===
79
+
80
+ create_backup() {
81
+ local file="$1"
82
+
83
+ # Only create backup if file exists
84
+ if [ ! -f "$file" ]; then
85
+ return 0
86
+ fi
87
+
88
+ local backup="${file}.backup.$$"
89
+ cp "$file" "$backup" || {
90
+ log_error "Failed to create backup of $file"
91
+ exit 1
92
+ }
93
+
94
+ BACKUP_FILES+=("$backup")
95
+ log_info "Created backup: ${backup##*/}"
96
+ }
97
+
98
+ restore_from_backups() {
99
+ if [ ${#BACKUP_FILES[@]} -eq 0 ]; then
100
+ return 0
101
+ fi
102
+
103
+ log_info "Restoring files from backups..."
104
+
105
+ for backup in "${BACKUP_FILES[@]}"; do
106
+ # Extract original filename by removing .backup.$$ suffix
107
+ local original="${backup%.backup.*}"
108
+
109
+ if [ -f "$backup" ]; then
110
+ mv "$backup" "$original"
111
+ log_success "Restored: ${original##*/}"
112
+ fi
113
+ done
114
+ }
115
+
116
+ cleanup_backups() {
117
+ # Clean up backup files after successful release
118
+ for backup in "${BACKUP_FILES[@]}"; do
119
+ if [ -f "$backup" ]; then
120
+ rm -f "$backup"
121
+ fi
122
+ done
123
+ }
124
+
63
125
  # === CLEANUP AND ROLLBACK ===
64
126
 
65
127
  cleanup() {
@@ -83,28 +145,17 @@ cleanup() {
83
145
  log_success "Rolled back commit (working directory preserved)"
84
146
  fi
85
147
 
86
- # Restore modified files only (not untracked files)
87
- if [ ${#MODIFIED_FILES[@]} -gt 0 ]; then
88
- git restore --staged "${MODIFIED_FILES[@]}" 2>/dev/null || true
89
- git restore "${MODIFIED_FILES[@]}" 2>/dev/null || true
90
- log_success "Restored modified package.json files"
91
- fi
92
-
93
- # Restore stash if we created one
94
- if [ -n "$STASH_CREATED" ]; then
95
- if git stash list | grep -q "release.sh: temporary stash"; then
96
- git stash pop >/dev/null 2>&1 || {
97
- log_warning "Stash pop failed with conflicts. Use 'git stash list' to see stashes."
98
- log_info "Manually restore with: git stash pop"
99
- }
100
- fi
101
- log_success "Stashed changes restored (or available in stash list)"
102
- fi
148
+ # SAFE ROLLBACK: Restore from backups instead of git restore
149
+ # This preserves any manual edits made before running the script
150
+ restore_from_backups
103
151
 
104
152
  echo ""
105
- log_info "Rollback complete. Repository state restored."
153
+ log_info "Rollback complete. Files restored from backups."
106
154
  echo ""
107
155
  exit $exit_code
156
+ else
157
+ # Success - clean up backup files
158
+ cleanup_backups
108
159
  fi
109
160
  }
110
161
 
@@ -132,15 +183,141 @@ run_preflight_checks() {
132
183
  fi
133
184
  log_success "On branch: $BRANCH"
134
185
 
135
- # Stash uncommitted changes to preserve user work
186
+ # Auto-commit uncommitted changes before release
136
187
  if ! git diff-index --quiet HEAD -- 2>/dev/null; then
137
- log_warning "Uncommitted changes detected. Stashing for safety..."
138
- git stash push -m "release.sh: temporary stash $(date +%Y%m%d-%H%M%S)" >/dev/null 2>&1 || {
139
- log_error "Failed to stash changes. Please commit or stash manually."
188
+ log_info "Uncommitted changes detected. Auto-committing before release..."
189
+
190
+ # Get file counts by status
191
+ MODIFIED_COUNT=$(git diff --name-only | wc -l)
192
+ STAGED_COUNT=$(git diff --cached --name-only | wc -l)
193
+ UNTRACKED_COUNT=$(git ls-files --others --exclude-standard | wc -l)
194
+ TOTAL_COUNT=$((MODIFIED_COUNT + STAGED_COUNT + UNTRACKED_COUNT))
195
+
196
+ # Stage ALL changes (modified, deleted, new files)
197
+ git add -A
198
+
199
+ # Get detailed file list for commit body
200
+ FILE_LIST=$(git diff --cached --name-status | sed 's/^/ /')
201
+
202
+ # Detect commit type based on changed files
203
+ local commit_type="chore"
204
+ local commit_scope=""
205
+ local commit_desc="update project files"
206
+
207
+ # Get file changes with status (A=added, M=modified, D=deleted)
208
+ local file_status=$(git diff --cached --name-status)
209
+
210
+ # Count different types of changes
211
+ local new_agents=$(echo "$file_status" | grep "^A.*\.claude/agents/.*\.md$" | wc -l)
212
+ local new_skills=$(echo "$file_status" | grep "^A.*\.claude/skills/.*/SKILL\.md$" | wc -l)
213
+ local new_commands=$(echo "$file_status" | grep "^A.*\.claude/commands/.*\.md$" | wc -l)
214
+ local modified_agents=$(echo "$file_status" | grep "^M.*\.claude/agents/.*\.md$" | wc -l)
215
+ local modified_scripts=$(echo "$file_status" | grep "^M.*\.claude/scripts/.*\.sh$" | wc -l)
216
+ local modified_skills=$(echo "$file_status" | grep "^M.*\.claude/skills/.*/SKILL\.md$" | wc -l)
217
+ local modified_commands=$(echo "$file_status" | grep "^M.*\.claude/commands/.*\.md$" | wc -l)
218
+ local modified_docs=$(echo "$file_status" | grep "\.md$" | grep -v "\.claude/" | wc -l)
219
+ local modified_mcp=$(echo "$file_status" | grep "mcp/.*\.json$" | wc -l)
220
+
221
+ # Priority-based commit type detection (most specific first)
222
+
223
+ # 1. New agents (highest priority for features)
224
+ if [ "$new_agents" -gt 0 ]; then
225
+ commit_type="feat"
226
+ commit_scope="agents"
227
+ local agent_file=$(echo "$file_status" | grep "^A.*\.claude/agents/.*\.md$" | head -1 | awk '{print $2}')
228
+ local agent_name=$(basename "$agent_file" .md)
229
+ if [ "$new_agents" -eq 1 ]; then
230
+ commit_desc="add ${agent_name} agent"
231
+ else
232
+ commit_desc="add ${new_agents} new agents (${agent_name}, ...)"
233
+ fi
234
+
235
+ # 2. New skills
236
+ elif [ "$new_skills" -gt 0 ]; then
237
+ commit_type="feat"
238
+ commit_scope="skills"
239
+ local skill_file=$(echo "$file_status" | grep "^A.*\.claude/skills/.*/SKILL\.md$" | head -1 | awk '{print $2}')
240
+ local skill_name=$(echo "$skill_file" | cut -d'/' -f4)
241
+ if [ "$new_skills" -eq 1 ]; then
242
+ commit_desc="add ${skill_name} skill"
243
+ else
244
+ commit_desc="add ${new_skills} new skills (${skill_name}, ...)"
245
+ fi
246
+
247
+ # 3. New commands
248
+ elif [ "$new_commands" -gt 0 ]; then
249
+ commit_type="feat"
250
+ commit_scope="commands"
251
+ local cmd_file=$(echo "$file_status" | grep "^A.*\.claude/commands/.*\.md$" | head -1 | awk '{print $2}')
252
+ local cmd_name=$(basename "$cmd_file" .md)
253
+ if [ "$new_commands" -eq 1 ]; then
254
+ commit_desc="add ${cmd_name} command"
255
+ else
256
+ commit_desc="add ${new_commands} new commands"
257
+ fi
258
+
259
+ # 4. Modified skills (features)
260
+ elif [ "$modified_skills" -gt 0 ]; then
261
+ commit_type="feat"
262
+ commit_scope="skills"
263
+ commit_desc="update skill implementations"
264
+
265
+ # 5. Modified commands (features)
266
+ elif [ "$modified_commands" -gt 0 ]; then
267
+ commit_type="feat"
268
+ commit_scope="commands"
269
+ commit_desc="update slash commands"
270
+
271
+ # 6. Modified scripts (chore)
272
+ elif [ "$modified_scripts" -gt 0 ]; then
273
+ commit_type="chore"
274
+ commit_scope="scripts"
275
+ commit_desc="update automation scripts"
276
+
277
+ # 7. Modified agents (chore)
278
+ elif [ "$modified_agents" -gt 0 ]; then
279
+ commit_type="chore"
280
+ commit_scope="agents"
281
+ commit_desc="update agent configurations"
282
+
283
+ # 8. Modified MCP configs (chore)
284
+ elif [ "$modified_mcp" -gt 0 ]; then
285
+ commit_type="chore"
286
+ commit_scope="mcp"
287
+ commit_desc="update MCP server configurations"
288
+
289
+ # 9. Documentation changes
290
+ elif [ "$modified_docs" -gt 0 ]; then
291
+ commit_type="docs"
292
+ commit_desc="update documentation"
293
+ fi
294
+
295
+ # Generate commit message with detected type
296
+ if [ -n "$commit_scope" ]; then
297
+ COMMIT_MSG="${commit_type}(${commit_scope}): ${commit_desc}"
298
+ else
299
+ COMMIT_MSG="${commit_type}: ${commit_desc}"
300
+ fi
301
+
302
+ COMMIT_MSG="${COMMIT_MSG}
303
+
304
+ Auto-committed ${TOTAL_COUNT} file(s) before creating release.
305
+
306
+ Files changed:
307
+ ${FILE_LIST}
308
+
309
+ 🤖 Generated with [Claude Code](https://claude.com/claude-code)
310
+
311
+ Co-Authored-By: Claude <noreply@anthropic.com>"
312
+
313
+ # Create commit
314
+ git commit -m "$COMMIT_MSG" >/dev/null 2>&1 || {
315
+ log_error "Failed to auto-commit changes"
140
316
  exit 1
141
317
  }
142
- STASH_CREATED="true"
143
- log_success "Changes stashed (will be restored on exit)"
318
+
319
+ log_success "Changes committed (${TOTAL_COUNT} files)"
320
+ log_info "Commit type: ${commit_type}${commit_scope:+(${commit_scope})}: ${commit_desc}"
144
321
  fi
145
322
 
146
323
  # Check if remote is configured
@@ -226,6 +403,9 @@ parse_commits() {
226
403
  local fix_pattern='^fix(\([^)]+\))?:'
227
404
  local refactor_pattern='^refactor(\([^)]+\))?:'
228
405
  local perf_pattern='^perf(\([^)]+\))?:'
406
+ local security_pattern='^security(\([^)]+\))?:'
407
+ local deprecate_pattern='^deprecate(\([^)]+\))?:'
408
+ local remove_pattern='^remove(\([^)]+\))?:'
229
409
 
230
410
  for commit in "${ALL_COMMITS[@]}"; do
231
411
  local hash=$(echo "$commit" | awk '{print $1}')
@@ -234,12 +414,21 @@ parse_commits() {
234
414
  # Check for breaking changes
235
415
  if [[ "$message" =~ $breaking_pattern ]] || echo "$message" | grep -q "BREAKING CHANGE:"; then
236
416
  BREAKING_CHANGES+=("$commit")
417
+ # Check for security fixes (high priority!)
418
+ elif [[ "$message" =~ $security_pattern ]]; then
419
+ SECURITY_FIXES+=("$commit")
237
420
  # Check for features
238
421
  elif [[ "$message" =~ $feat_pattern ]]; then
239
422
  FEATURES+=("$commit")
240
423
  # Check for fixes
241
424
  elif [[ "$message" =~ $fix_pattern ]]; then
242
425
  FIXES+=("$commit")
426
+ # Check for deprecations
427
+ elif [[ "$message" =~ $deprecate_pattern ]]; then
428
+ DEPRECATIONS+=("$commit")
429
+ # Check for removals
430
+ elif [[ "$message" =~ $remove_pattern ]]; then
431
+ REMOVALS+=("$commit")
243
432
  # Check for refactors
244
433
  elif [[ "$message" =~ $refactor_pattern ]]; then
245
434
  REFACTORS+=("$commit")
@@ -255,8 +444,11 @@ parse_commits() {
255
444
  # Display commit summary
256
445
  log_info "Commit summary:"
257
446
  [ ${#BREAKING_CHANGES[@]} -gt 0 ] && echo " 🔥 ${#BREAKING_CHANGES[@]} breaking changes"
447
+ [ ${#SECURITY_FIXES[@]} -gt 0 ] && echo " 🔒 ${#SECURITY_FIXES[@]} security fixes"
258
448
  [ ${#FEATURES[@]} -gt 0 ] && echo " ✨ ${#FEATURES[@]} features"
259
449
  [ ${#FIXES[@]} -gt 0 ] && echo " 🐛 ${#FIXES[@]} bug fixes"
450
+ [ ${#DEPRECATIONS[@]} -gt 0 ] && echo " ⚠️ ${#DEPRECATIONS[@]} deprecations"
451
+ [ ${#REMOVALS[@]} -gt 0 ] && echo " 🗑️ ${#REMOVALS[@]} removals"
260
452
  [ ${#REFACTORS[@]} -gt 0 ] && echo " ♻️ ${#REFACTORS[@]} refactors"
261
453
  [ ${#PERF[@]} -gt 0 ] && echo " ⚡ ${#PERF[@]} performance improvements"
262
454
  [ ${#OTHER_CHANGES[@]} -gt 0 ] && echo " 📝 ${#OTHER_CHANGES[@]} other changes"
@@ -286,6 +478,9 @@ detect_version_bump() {
286
478
  elif [ ${#FEATURES[@]} -gt 0 ]; then
287
479
  BUMP_TYPE="minor"
288
480
  AUTO_DETECT_REASON="Found ${#FEATURES[@]} new feature(s)"
481
+ elif [ ${#SECURITY_FIXES[@]} -gt 0 ]; then
482
+ BUMP_TYPE="patch"
483
+ AUTO_DETECT_REASON="Found ${#SECURITY_FIXES[@]} security fix(es)"
289
484
  elif [ ${#FIXES[@]} -gt 0 ]; then
290
485
  BUMP_TYPE="patch"
291
486
  AUTO_DETECT_REASON="Found ${#FIXES[@]} bug fix(es)"
@@ -338,6 +533,15 @@ generate_changelog_entry() {
338
533
 
339
534
  EOF
340
535
 
536
+ # Security section (FIRST - highest priority!)
537
+ if [ ${#SECURITY_FIXES[@]} -gt 0 ]; then
538
+ echo "### Security"
539
+ for commit in "${SECURITY_FIXES[@]}"; do
540
+ format_changelog_line "$commit"
541
+ done
542
+ echo ""
543
+ fi
544
+
341
545
  # Added section (features)
342
546
  if [ ${#FEATURES[@]} -gt 0 ]; then
343
547
  echo "### Added"
@@ -362,6 +566,24 @@ EOF
362
566
  echo ""
363
567
  fi
364
568
 
569
+ # Deprecated section
570
+ if [ ${#DEPRECATIONS[@]} -gt 0 ]; then
571
+ echo "### Deprecated"
572
+ for commit in "${DEPRECATIONS[@]}"; do
573
+ format_changelog_line "$commit"
574
+ done
575
+ echo ""
576
+ fi
577
+
578
+ # Removed section
579
+ if [ ${#REMOVALS[@]} -gt 0 ]; then
580
+ echo "### Removed"
581
+ for commit in "${REMOVALS[@]}"; do
582
+ format_changelog_line "$commit"
583
+ done
584
+ echo ""
585
+ fi
586
+
365
587
  # Fixed section
366
588
  if [ ${#FIXES[@]} -gt 0 ]; then
367
589
  echo "### Fixed"
@@ -414,6 +636,9 @@ update_package_files() {
414
636
 
415
637
  while IFS= read -r pkg; do
416
638
  if [ -n "$pkg" ]; then
639
+ # Create backup BEFORE modifying
640
+ create_backup "$pkg"
641
+
417
642
  # Track for rollback
418
643
  MODIFIED_FILES+=("$pkg")
419
644
 
@@ -448,6 +673,9 @@ update_changelog() {
448
673
 
449
674
  local changelog_file="$PROJECT_ROOT/CHANGELOG.md"
450
675
 
676
+ # Create backup BEFORE modifying
677
+ create_backup "$changelog_file"
678
+
451
679
  # Track for rollback
452
680
  MODIFIED_FILES+=("$changelog_file")
453
681
 
@@ -514,8 +742,11 @@ show_preview() {
514
742
  EOF
515
743
 
516
744
  [ ${#BREAKING_CHANGES[@]} -gt 0 ] && echo " 🔥 ${#BREAKING_CHANGES[@]} breaking changes"
745
+ [ ${#SECURITY_FIXES[@]} -gt 0 ] && echo " 🔒 ${#SECURITY_FIXES[@]} security fixes"
517
746
  [ ${#FEATURES[@]} -gt 0 ] && echo " ✨ ${#FEATURES[@]} features"
518
747
  [ ${#FIXES[@]} -gt 0 ] && echo " 🐛 ${#FIXES[@]} bug fixes"
748
+ [ ${#DEPRECATIONS[@]} -gt 0 ] && echo " ⚠️ ${#DEPRECATIONS[@]} deprecations"
749
+ [ ${#REMOVALS[@]} -gt 0 ] && echo " 🗑️ ${#REMOVALS[@]} removals"
519
750
  [ ${#REFACTORS[@]} -gt 0 ] && echo " ♻️ ${#REFACTORS[@]} refactors"
520
751
  [ ${#PERF[@]} -gt 0 ] && echo " ⚡ ${#PERF[@]} performance improvements"
521
752
  [ ${#OTHER_CHANGES[@]} -gt 0 ] && echo " 📝 ${#OTHER_CHANGES[@]} other changes"
@@ -591,6 +822,9 @@ execute_release() {
591
822
  log_info "Executing release..."
592
823
  echo ""
593
824
 
825
+ # Clean up backup files BEFORE staging
826
+ cleanup_backups
827
+
594
828
  # Stage all changes
595
829
  log_info "Staging changes..."
596
830
  git add -A
@@ -706,17 +940,6 @@ main() {
706
940
  update_changelog "$NEW_VERSION" "$DATE"
707
941
  execute_release
708
942
 
709
- # Success! Restore stash if created
710
- if [ -n "$STASH_CREATED" ]; then
711
- log_info "Restoring stashed changes..."
712
- if git stash list | grep -q "release.sh: temporary stash"; then
713
- git stash pop >/dev/null 2>&1 || {
714
- log_warning "Stash pop had conflicts. Check 'git stash list'"
715
- log_info "Manually restore with: git stash pop"
716
- }
717
- fi
718
- fi
719
-
720
943
  echo ""
721
944
  echo "╔═══════════════════════════════════════════════════════════╗"
722
945
  echo "║ RELEASE SUCCESSFUL! 🎉 ║"
@@ -725,9 +948,6 @@ main() {
725
948
  log_success "Released v$NEW_VERSION"
726
949
  log_success "Tag: v$NEW_VERSION"
727
950
  log_success "Branch: $BRANCH"
728
- if [ -n "$STASH_CREATED" ]; then
729
- log_success "Stashed changes restored"
730
- fi
731
951
  echo ""
732
952
  log_info "Next steps:"
733
953
  echo " • Verify release on GitHub: git remote -v"