@zenuml/core 3.41.4 → 3.41.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,728 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Update agent context files with information from plan.md
4
+ #
5
+ # This script maintains AI agent context files by parsing feature specifications
6
+ # and updating agent-specific configuration files with project information.
7
+ #
8
+ # MAIN FUNCTIONS:
9
+ # 1. Environment Validation
10
+ # - Verifies git repository structure and branch information
11
+ # - Checks for required plan.md files and templates
12
+ # - Validates file permissions and accessibility
13
+ #
14
+ # 2. Plan Data Extraction
15
+ # - Parses plan.md files to extract project metadata
16
+ # - Identifies language/version, frameworks, databases, and project types
17
+ # - Handles missing or incomplete specification data gracefully
18
+ #
19
+ # 3. Agent File Management
20
+ # - Creates new agent context files from templates when needed
21
+ # - Updates existing agent files with new project information
22
+ # - Preserves manual additions and custom configurations
23
+ # - Supports multiple AI agent formats and directory structures
24
+ #
25
+ # 4. Content Generation
26
+ # - Generates language-specific build/test commands
27
+ # - Creates appropriate project directory structures
28
+ # - Updates technology stacks and recent changes sections
29
+ # - Maintains consistent formatting and timestamps
30
+ #
31
+ # 5. Multi-Agent Support
32
+ # - Handles agent-specific file paths and naming conventions
33
+ # - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf, Kilo Code, Auggie CLI, or Amazon Q Developer CLI
34
+ # - Can update single agents or all existing agent files
35
+ # - Creates default Claude file if no agent files exist
36
+ #
37
+ # Usage: ./update-agent-context.sh [agent_type]
38
+ # Agent types: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|q
39
+ # Leave empty to update all existing agent files
40
+
41
+ set -e
42
+
43
+ # Enable strict error handling
44
+ set -u
45
+ set -o pipefail
46
+
47
+ #==============================================================================
48
+ # Configuration and Global Variables
49
+ #==============================================================================
50
+
51
+ # Get script directory and load common functions
52
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
53
+ source "$SCRIPT_DIR/common.sh"
54
+
55
+ # Get all paths and variables from common functions
56
+ eval $(get_feature_paths)
57
+
58
+ NEW_PLAN="$IMPL_PLAN" # Alias for compatibility with existing code
59
+ AGENT_TYPE="${1:-}"
60
+
61
+ # Agent-specific file paths
62
+ CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"
63
+ GEMINI_FILE="$REPO_ROOT/GEMINI.md"
64
+ COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"
65
+ CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"
66
+ QWEN_FILE="$REPO_ROOT/QWEN.md"
67
+ AGENTS_FILE="$REPO_ROOT/AGENTS.md"
68
+ WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
69
+ KILOCODE_FILE="$REPO_ROOT/.kilocode/rules/specify-rules.md"
70
+ AUGGIE_FILE="$REPO_ROOT/.augment/rules/specify-rules.md"
71
+ ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md"
72
+ Q_FILE="$REPO_ROOT/AGENTS.md"
73
+
74
+ # Template file
75
+ TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md"
76
+
77
+ # Global variables for parsed plan data
78
+ NEW_LANG=""
79
+ NEW_FRAMEWORK=""
80
+ NEW_DB=""
81
+ NEW_PROJECT_TYPE=""
82
+
83
+ #==============================================================================
84
+ # Utility Functions
85
+ #==============================================================================
86
+
87
+ log_info() {
88
+ echo "INFO: $1"
89
+ }
90
+
91
+ log_success() {
92
+ echo "✓ $1"
93
+ }
94
+
95
+ log_error() {
96
+ echo "ERROR: $1" >&2
97
+ }
98
+
99
+ log_warning() {
100
+ echo "WARNING: $1" >&2
101
+ }
102
+
103
+ # Cleanup function for temporary files
104
+ cleanup() {
105
+ local exit_code=$?
106
+ rm -f /tmp/agent_update_*_$$
107
+ rm -f /tmp/manual_additions_$$
108
+ exit $exit_code
109
+ }
110
+
111
+ # Set up cleanup trap
112
+ trap cleanup EXIT INT TERM
113
+
114
+ #==============================================================================
115
+ # Validation Functions
116
+ #==============================================================================
117
+
118
+ validate_environment() {
119
+ # Check if we have a current branch/feature (git or non-git)
120
+ if [[ -z "$CURRENT_BRANCH" ]]; then
121
+ log_error "Unable to determine current feature"
122
+ if [[ "$HAS_GIT" == "true" ]]; then
123
+ log_info "Make sure you're on a feature branch"
124
+ else
125
+ log_info "Set SPECIFY_FEATURE environment variable or create a feature first"
126
+ fi
127
+ exit 1
128
+ fi
129
+
130
+ # Check if plan.md exists
131
+ if [[ ! -f "$NEW_PLAN" ]]; then
132
+ log_error "No plan.md found at $NEW_PLAN"
133
+ log_info "Make sure you're working on a feature with a corresponding spec directory"
134
+ if [[ "$HAS_GIT" != "true" ]]; then
135
+ log_info "Use: export SPECIFY_FEATURE=your-feature-name or create a new feature first"
136
+ fi
137
+ exit 1
138
+ fi
139
+
140
+ # Check if template exists (needed for new files)
141
+ if [[ ! -f "$TEMPLATE_FILE" ]]; then
142
+ log_warning "Template file not found at $TEMPLATE_FILE"
143
+ log_warning "Creating new agent files will fail"
144
+ fi
145
+ }
146
+
147
+ #==============================================================================
148
+ # Plan Parsing Functions
149
+ #==============================================================================
150
+
151
+ extract_plan_field() {
152
+ local field_pattern="$1"
153
+ local plan_file="$2"
154
+
155
+ grep "^\*\*${field_pattern}\*\*: " "$plan_file" 2>/dev/null | \
156
+ head -1 | \
157
+ sed "s|^\*\*${field_pattern}\*\*: ||" | \
158
+ sed 's/^[ \t]*//;s/[ \t]*$//' | \
159
+ grep -v "NEEDS CLARIFICATION" | \
160
+ grep -v "^N/A$" || echo ""
161
+ }
162
+
163
+ parse_plan_data() {
164
+ local plan_file="$1"
165
+
166
+ if [[ ! -f "$plan_file" ]]; then
167
+ log_error "Plan file not found: $plan_file"
168
+ return 1
169
+ fi
170
+
171
+ if [[ ! -r "$plan_file" ]]; then
172
+ log_error "Plan file is not readable: $plan_file"
173
+ return 1
174
+ fi
175
+
176
+ log_info "Parsing plan data from $plan_file"
177
+
178
+ NEW_LANG=$(extract_plan_field "Language/Version" "$plan_file")
179
+ NEW_FRAMEWORK=$(extract_plan_field "Primary Dependencies" "$plan_file")
180
+ NEW_DB=$(extract_plan_field "Storage" "$plan_file")
181
+ NEW_PROJECT_TYPE=$(extract_plan_field "Project Type" "$plan_file")
182
+
183
+ # Log what we found
184
+ if [[ -n "$NEW_LANG" ]]; then
185
+ log_info "Found language: $NEW_LANG"
186
+ else
187
+ log_warning "No language information found in plan"
188
+ fi
189
+
190
+ if [[ -n "$NEW_FRAMEWORK" ]]; then
191
+ log_info "Found framework: $NEW_FRAMEWORK"
192
+ fi
193
+
194
+ if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
195
+ log_info "Found database: $NEW_DB"
196
+ fi
197
+
198
+ if [[ -n "$NEW_PROJECT_TYPE" ]]; then
199
+ log_info "Found project type: $NEW_PROJECT_TYPE"
200
+ fi
201
+ }
202
+
203
+ format_technology_stack() {
204
+ local lang="$1"
205
+ local framework="$2"
206
+ local parts=()
207
+
208
+ # Add non-empty parts
209
+ [[ -n "$lang" && "$lang" != "NEEDS CLARIFICATION" ]] && parts+=("$lang")
210
+ [[ -n "$framework" && "$framework" != "NEEDS CLARIFICATION" && "$framework" != "N/A" ]] && parts+=("$framework")
211
+
212
+ # Join with proper formatting
213
+ if [[ ${#parts[@]} -eq 0 ]]; then
214
+ echo ""
215
+ elif [[ ${#parts[@]} -eq 1 ]]; then
216
+ echo "${parts[0]}"
217
+ else
218
+ # Join multiple parts with " + "
219
+ local result="${parts[0]}"
220
+ for ((i=1; i<${#parts[@]}; i++)); do
221
+ result="$result + ${parts[i]}"
222
+ done
223
+ echo "$result"
224
+ fi
225
+ }
226
+
227
+ #==============================================================================
228
+ # Template and Content Generation Functions
229
+ #==============================================================================
230
+
231
+ get_project_structure() {
232
+ local project_type="$1"
233
+
234
+ if [[ "$project_type" == *"web"* ]]; then
235
+ echo "backend/\\nfrontend/\\ntests/"
236
+ else
237
+ echo "src/\\ntests/"
238
+ fi
239
+ }
240
+
241
+ get_commands_for_language() {
242
+ local lang="$1"
243
+
244
+ case "$lang" in
245
+ *"Python"*)
246
+ echo "cd src && pytest && ruff check ."
247
+ ;;
248
+ *"Rust"*)
249
+ echo "cargo test && cargo clippy"
250
+ ;;
251
+ *"JavaScript"*|*"TypeScript"*)
252
+ echo "npm test && npm run lint"
253
+ ;;
254
+ *)
255
+ echo "# Add commands for $lang"
256
+ ;;
257
+ esac
258
+ }
259
+
260
+ get_language_conventions() {
261
+ local lang="$1"
262
+ echo "$lang: Follow standard conventions"
263
+ }
264
+
265
+ create_new_agent_file() {
266
+ local target_file="$1"
267
+ local temp_file="$2"
268
+ local project_name="$3"
269
+ local current_date="$4"
270
+
271
+ if [[ ! -f "$TEMPLATE_FILE" ]]; then
272
+ log_error "Template not found at $TEMPLATE_FILE"
273
+ return 1
274
+ fi
275
+
276
+ if [[ ! -r "$TEMPLATE_FILE" ]]; then
277
+ log_error "Template file is not readable: $TEMPLATE_FILE"
278
+ return 1
279
+ fi
280
+
281
+ log_info "Creating new agent context file from template..."
282
+
283
+ if ! cp "$TEMPLATE_FILE" "$temp_file"; then
284
+ log_error "Failed to copy template file"
285
+ return 1
286
+ fi
287
+
288
+ # Replace template placeholders
289
+ local project_structure
290
+ project_structure=$(get_project_structure "$NEW_PROJECT_TYPE")
291
+
292
+ local commands
293
+ commands=$(get_commands_for_language "$NEW_LANG")
294
+
295
+ local language_conventions
296
+ language_conventions=$(get_language_conventions "$NEW_LANG")
297
+
298
+ # Perform substitutions with error checking using safer approach
299
+ # Escape special characters for sed by using a different delimiter or escaping
300
+ local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g')
301
+ local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g')
302
+ local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g')
303
+
304
+ # Build technology stack and recent change strings conditionally
305
+ local tech_stack
306
+ if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
307
+ tech_stack="- $escaped_lang + $escaped_framework ($escaped_branch)"
308
+ elif [[ -n "$escaped_lang" ]]; then
309
+ tech_stack="- $escaped_lang ($escaped_branch)"
310
+ elif [[ -n "$escaped_framework" ]]; then
311
+ tech_stack="- $escaped_framework ($escaped_branch)"
312
+ else
313
+ tech_stack="- ($escaped_branch)"
314
+ fi
315
+
316
+ local recent_change
317
+ if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
318
+ recent_change="- $escaped_branch: Added $escaped_lang + $escaped_framework"
319
+ elif [[ -n "$escaped_lang" ]]; then
320
+ recent_change="- $escaped_branch: Added $escaped_lang"
321
+ elif [[ -n "$escaped_framework" ]]; then
322
+ recent_change="- $escaped_branch: Added $escaped_framework"
323
+ else
324
+ recent_change="- $escaped_branch: Added"
325
+ fi
326
+
327
+ local substitutions=(
328
+ "s|\[PROJECT NAME\]|$project_name|"
329
+ "s|\[DATE\]|$current_date|"
330
+ "s|\[EXTRACTED FROM ALL PLAN.MD FILES\]|$tech_stack|"
331
+ "s|\[ACTUAL STRUCTURE FROM PLANS\]|$project_structure|g"
332
+ "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$commands|"
333
+ "s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$language_conventions|"
334
+ "s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|$recent_change|"
335
+ )
336
+
337
+ for substitution in "${substitutions[@]}"; do
338
+ if ! sed -i.bak -e "$substitution" "$temp_file"; then
339
+ log_error "Failed to perform substitution: $substitution"
340
+ rm -f "$temp_file" "$temp_file.bak"
341
+ return 1
342
+ fi
343
+ done
344
+
345
+ # Convert \n sequences to actual newlines
346
+ newline=$(printf '\n')
347
+ sed -i.bak2 "s/\\\\n/${newline}/g" "$temp_file"
348
+
349
+ # Clean up backup files
350
+ rm -f "$temp_file.bak" "$temp_file.bak2"
351
+
352
+ return 0
353
+ }
354
+
355
+
356
+
357
+
358
+ update_existing_agent_file() {
359
+ local target_file="$1"
360
+ local current_date="$2"
361
+
362
+ log_info "Updating existing agent context file..."
363
+
364
+ # Use a single temporary file for atomic update
365
+ local temp_file
366
+ temp_file=$(mktemp) || {
367
+ log_error "Failed to create temporary file"
368
+ return 1
369
+ }
370
+
371
+ # Process the file in one pass
372
+ local tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK")
373
+ local new_tech_entries=()
374
+ local new_change_entry=""
375
+
376
+ # Prepare new technology entries
377
+ if [[ -n "$tech_stack" ]] && ! grep -q "$tech_stack" "$target_file"; then
378
+ new_tech_entries+=("- $tech_stack ($CURRENT_BRANCH)")
379
+ fi
380
+
381
+ if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]] && ! grep -q "$NEW_DB" "$target_file"; then
382
+ new_tech_entries+=("- $NEW_DB ($CURRENT_BRANCH)")
383
+ fi
384
+
385
+ # Prepare new change entry
386
+ if [[ -n "$tech_stack" ]]; then
387
+ new_change_entry="- $CURRENT_BRANCH: Added $tech_stack"
388
+ elif [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]]; then
389
+ new_change_entry="- $CURRENT_BRANCH: Added $NEW_DB"
390
+ fi
391
+
392
+ # Process file line by line
393
+ local in_tech_section=false
394
+ local in_changes_section=false
395
+ local tech_entries_added=false
396
+ local changes_entries_added=false
397
+ local existing_changes_count=0
398
+
399
+ while IFS= read -r line || [[ -n "$line" ]]; do
400
+ # Handle Active Technologies section
401
+ if [[ "$line" == "## Active Technologies" ]]; then
402
+ echo "$line" >> "$temp_file"
403
+ in_tech_section=true
404
+ continue
405
+ elif [[ $in_tech_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
406
+ # Add new tech entries before closing the section
407
+ if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
408
+ printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
409
+ tech_entries_added=true
410
+ fi
411
+ echo "$line" >> "$temp_file"
412
+ in_tech_section=false
413
+ continue
414
+ elif [[ $in_tech_section == true ]] && [[ -z "$line" ]]; then
415
+ # Add new tech entries before empty line in tech section
416
+ if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
417
+ printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
418
+ tech_entries_added=true
419
+ fi
420
+ echo "$line" >> "$temp_file"
421
+ continue
422
+ fi
423
+
424
+ # Handle Recent Changes section
425
+ if [[ "$line" == "## Recent Changes" ]]; then
426
+ echo "$line" >> "$temp_file"
427
+ # Add new change entry right after the heading
428
+ if [[ -n "$new_change_entry" ]]; then
429
+ echo "$new_change_entry" >> "$temp_file"
430
+ fi
431
+ in_changes_section=true
432
+ changes_entries_added=true
433
+ continue
434
+ elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
435
+ echo "$line" >> "$temp_file"
436
+ in_changes_section=false
437
+ continue
438
+ elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then
439
+ # Keep only first 2 existing changes
440
+ if [[ $existing_changes_count -lt 2 ]]; then
441
+ echo "$line" >> "$temp_file"
442
+ ((existing_changes_count++))
443
+ fi
444
+ continue
445
+ fi
446
+
447
+ # Update timestamp
448
+ if [[ "$line" =~ \*\*Last\ updated\*\*:.*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then
449
+ echo "$line" | sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/$current_date/" >> "$temp_file"
450
+ else
451
+ echo "$line" >> "$temp_file"
452
+ fi
453
+ done < "$target_file"
454
+
455
+ # Post-loop check: if we're still in the Active Technologies section and haven't added new entries
456
+ if [[ $in_tech_section == true ]] && [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
457
+ printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
458
+ fi
459
+
460
+ # Move temp file to target atomically
461
+ if ! mv "$temp_file" "$target_file"; then
462
+ log_error "Failed to update target file"
463
+ rm -f "$temp_file"
464
+ return 1
465
+ fi
466
+
467
+ return 0
468
+ }
469
+ #==============================================================================
470
+ # Main Agent File Update Function
471
+ #==============================================================================
472
+
473
+ update_agent_file() {
474
+ local target_file="$1"
475
+ local agent_name="$2"
476
+
477
+ if [[ -z "$target_file" ]] || [[ -z "$agent_name" ]]; then
478
+ log_error "update_agent_file requires target_file and agent_name parameters"
479
+ return 1
480
+ fi
481
+
482
+ log_info "Updating $agent_name context file: $target_file"
483
+
484
+ local project_name
485
+ project_name=$(basename "$REPO_ROOT")
486
+ local current_date
487
+ current_date=$(date +%Y-%m-%d)
488
+
489
+ # Create directory if it doesn't exist
490
+ local target_dir
491
+ target_dir=$(dirname "$target_file")
492
+ if [[ ! -d "$target_dir" ]]; then
493
+ if ! mkdir -p "$target_dir"; then
494
+ log_error "Failed to create directory: $target_dir"
495
+ return 1
496
+ fi
497
+ fi
498
+
499
+ if [[ ! -f "$target_file" ]]; then
500
+ # Create new file from template
501
+ local temp_file
502
+ temp_file=$(mktemp) || {
503
+ log_error "Failed to create temporary file"
504
+ return 1
505
+ }
506
+
507
+ if create_new_agent_file "$target_file" "$temp_file" "$project_name" "$current_date"; then
508
+ if mv "$temp_file" "$target_file"; then
509
+ log_success "Created new $agent_name context file"
510
+ else
511
+ log_error "Failed to move temporary file to $target_file"
512
+ rm -f "$temp_file"
513
+ return 1
514
+ fi
515
+ else
516
+ log_error "Failed to create new agent file"
517
+ rm -f "$temp_file"
518
+ return 1
519
+ fi
520
+ else
521
+ # Update existing file
522
+ if [[ ! -r "$target_file" ]]; then
523
+ log_error "Cannot read existing file: $target_file"
524
+ return 1
525
+ fi
526
+
527
+ if [[ ! -w "$target_file" ]]; then
528
+ log_error "Cannot write to existing file: $target_file"
529
+ return 1
530
+ fi
531
+
532
+ if update_existing_agent_file "$target_file" "$current_date"; then
533
+ log_success "Updated existing $agent_name context file"
534
+ else
535
+ log_error "Failed to update existing agent file"
536
+ return 1
537
+ fi
538
+ fi
539
+
540
+ return 0
541
+ }
542
+
543
+ #==============================================================================
544
+ # Agent Selection and Processing
545
+ #==============================================================================
546
+
547
+ update_specific_agent() {
548
+ local agent_type="$1"
549
+
550
+ case "$agent_type" in
551
+ claude)
552
+ update_agent_file "$CLAUDE_FILE" "Claude Code"
553
+ ;;
554
+ gemini)
555
+ update_agent_file "$GEMINI_FILE" "Gemini CLI"
556
+ ;;
557
+ copilot)
558
+ update_agent_file "$COPILOT_FILE" "GitHub Copilot"
559
+ ;;
560
+ cursor)
561
+ update_agent_file "$CURSOR_FILE" "Cursor IDE"
562
+ ;;
563
+ qwen)
564
+ update_agent_file "$QWEN_FILE" "Qwen Code"
565
+ ;;
566
+ opencode)
567
+ update_agent_file "$AGENTS_FILE" "opencode"
568
+ ;;
569
+ codex)
570
+ update_agent_file "$AGENTS_FILE" "Codex CLI"
571
+ ;;
572
+ windsurf)
573
+ update_agent_file "$WINDSURF_FILE" "Windsurf"
574
+ ;;
575
+ kilocode)
576
+ update_agent_file "$KILOCODE_FILE" "Kilo Code"
577
+ ;;
578
+ auggie)
579
+ update_agent_file "$AUGGIE_FILE" "Auggie CLI"
580
+ ;;
581
+ roo)
582
+ update_agent_file "$ROO_FILE" "Roo Code"
583
+ ;;
584
+ q)
585
+ update_agent_file "$Q_FILE" "Amazon Q Developer CLI"
586
+ ;;
587
+ *)
588
+ log_error "Unknown agent type '$agent_type'"
589
+ log_error "Expected: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo|q"
590
+ exit 1
591
+ ;;
592
+ esac
593
+ }
594
+
595
+ update_all_existing_agents() {
596
+ local found_agent=false
597
+
598
+ # Check each possible agent file and update if it exists
599
+ if [[ -f "$CLAUDE_FILE" ]]; then
600
+ update_agent_file "$CLAUDE_FILE" "Claude Code"
601
+ found_agent=true
602
+ fi
603
+
604
+ if [[ -f "$GEMINI_FILE" ]]; then
605
+ update_agent_file "$GEMINI_FILE" "Gemini CLI"
606
+ found_agent=true
607
+ fi
608
+
609
+ if [[ -f "$COPILOT_FILE" ]]; then
610
+ update_agent_file "$COPILOT_FILE" "GitHub Copilot"
611
+ found_agent=true
612
+ fi
613
+
614
+ if [[ -f "$CURSOR_FILE" ]]; then
615
+ update_agent_file "$CURSOR_FILE" "Cursor IDE"
616
+ found_agent=true
617
+ fi
618
+
619
+ if [[ -f "$QWEN_FILE" ]]; then
620
+ update_agent_file "$QWEN_FILE" "Qwen Code"
621
+ found_agent=true
622
+ fi
623
+
624
+ if [[ -f "$AGENTS_FILE" ]]; then
625
+ update_agent_file "$AGENTS_FILE" "Codex/opencode"
626
+ found_agent=true
627
+ fi
628
+
629
+ if [[ -f "$WINDSURF_FILE" ]]; then
630
+ update_agent_file "$WINDSURF_FILE" "Windsurf"
631
+ found_agent=true
632
+ fi
633
+
634
+ if [[ -f "$KILOCODE_FILE" ]]; then
635
+ update_agent_file "$KILOCODE_FILE" "Kilo Code"
636
+ found_agent=true
637
+ fi
638
+
639
+ if [[ -f "$AUGGIE_FILE" ]]; then
640
+ update_agent_file "$AUGGIE_FILE" "Auggie CLI"
641
+ found_agent=true
642
+ fi
643
+
644
+ if [[ -f "$ROO_FILE" ]]; then
645
+ update_agent_file "$ROO_FILE" "Roo Code"
646
+ found_agent=true
647
+ fi
648
+
649
+ if [[ -f "$Q_FILE" ]]; then
650
+ update_agent_file "$Q_FILE" "Amazon Q Developer CLI"
651
+ found_agent=true
652
+ fi
653
+
654
+ # If no agent files exist, create a default Claude file
655
+ if [[ "$found_agent" == false ]]; then
656
+ log_info "No existing agent files found, creating default Claude file..."
657
+ update_agent_file "$CLAUDE_FILE" "Claude Code"
658
+ fi
659
+ }
660
+ print_summary() {
661
+ echo
662
+ log_info "Summary of changes:"
663
+
664
+ if [[ -n "$NEW_LANG" ]]; then
665
+ echo " - Added language: $NEW_LANG"
666
+ fi
667
+
668
+ if [[ -n "$NEW_FRAMEWORK" ]]; then
669
+ echo " - Added framework: $NEW_FRAMEWORK"
670
+ fi
671
+
672
+ if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
673
+ echo " - Added database: $NEW_DB"
674
+ fi
675
+
676
+ echo
677
+ log_info "Usage: $0 [claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|q]"
678
+ }
679
+
680
+ #==============================================================================
681
+ # Main Execution
682
+ #==============================================================================
683
+
684
+ main() {
685
+ # Validate environment before proceeding
686
+ validate_environment
687
+
688
+ log_info "=== Updating agent context files for feature $CURRENT_BRANCH ==="
689
+
690
+ # Parse the plan file to extract project information
691
+ if ! parse_plan_data "$NEW_PLAN"; then
692
+ log_error "Failed to parse plan data"
693
+ exit 1
694
+ fi
695
+
696
+ # Process based on agent type argument
697
+ local success=true
698
+
699
+ if [[ -z "$AGENT_TYPE" ]]; then
700
+ # No specific agent provided - update all existing agent files
701
+ log_info "No agent specified, updating all existing agent files..."
702
+ if ! update_all_existing_agents; then
703
+ success=false
704
+ fi
705
+ else
706
+ # Specific agent provided - update only that agent
707
+ log_info "Updating specific agent: $AGENT_TYPE"
708
+ if ! update_specific_agent "$AGENT_TYPE"; then
709
+ success=false
710
+ fi
711
+ fi
712
+
713
+ # Print summary
714
+ print_summary
715
+
716
+ if [[ "$success" == true ]]; then
717
+ log_success "Agent context update completed successfully"
718
+ exit 0
719
+ else
720
+ log_error "Agent context update completed with errors"
721
+ exit 1
722
+ fi
723
+ }
724
+
725
+ # Execute main function if script is run directly
726
+ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
727
+ main "$@"
728
+ fi