aidevops 3.8.81 → 3.8.84

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 (4) hide show
  1. package/VERSION +1 -1
  2. package/aidevops.sh +121 -56
  3. package/package.json +1 -1
  4. package/setup.sh +1 -1
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.8.81
1
+ 3.8.84
package/aidevops.sh CHANGED
@@ -5,7 +5,7 @@
5
5
  # AI DevOps Framework CLI
6
6
  # Usage: aidevops <command> [options]
7
7
  #
8
- # Version: 3.8.81
8
+ # Version: 3.8.84
9
9
 
10
10
  set -euo pipefail
11
11
 
@@ -878,6 +878,13 @@ cmd_status() {
878
878
  print_warning "Commit signing not configured — run: aidevops signing setup"
879
879
  fi
880
880
  echo ""
881
+ # t2424/GH#20030: Pulse operational counters (pre-dispatch aborts, etc.)
882
+ local stats_helper="$AGENTS_DIR/scripts/pulse-stats-helper.sh"
883
+ if [[ -x "$stats_helper" ]]; then
884
+ print_header "Pulse Stats"
885
+ "$stats_helper" status 2>/dev/null || print_info " (no stats recorded yet)"
886
+ echo ""
887
+ fi
881
888
  }
882
889
 
883
890
  # Update helpers (extracted for complexity reduction)
@@ -2585,44 +2592,118 @@ _upgrade_check_version() {
2585
2592
  fi
2586
2593
  }
2587
2594
 
2595
+ # t2434: Extract lines under "## <section>" until the next "## " header.
2596
+ # Skips ## Format block entirely (its content is documentation, not tasks).
2597
+ # Skips fenced code blocks.
2598
+ # Exact-match on the section header — no regex escaping concerns.
2599
+ _extract_todo_section() {
2600
+ local file="$1" section="$2"
2601
+ awk -v target="## $section" '
2602
+ /^## Format/ { in_format=1; next }
2603
+ in_format && /^## / { in_format=0 }
2604
+ in_format { next }
2605
+ /^```/ { in_codeblock = !in_codeblock; next }
2606
+ in_codeblock { next }
2607
+ $0 == target { found=1; next }
2608
+ found && /^## / { exit }
2609
+ found
2610
+ ' "$file" 2>/dev/null || echo ""
2611
+ }
2612
+
2613
+ # t2434: Filter stdin, removing only the literal Format-block placeholder IDs
2614
+ # (tXXX, tYYY, tZZZ). Real-world repos have historic IDs that don't follow the
2615
+ # strict t<digits> shape (e.g. "t059b", "t043-merge" from awardsapp) — we must
2616
+ # preserve those. A blocklist is safer than an allowlist here: extraction
2617
+ # already skips the Format section, so the filter is a secondary guard rather
2618
+ # than primary validation.
2619
+ _filter_todo_placeholders() {
2620
+ awk '
2621
+ !/^- \[[ x-]\] t/ { print; next }
2622
+ {
2623
+ id = $0
2624
+ sub(/^- \[[ x-]\] /, "", id)
2625
+ sub(/ .*/, "", id)
2626
+ if (id == "tXXX" || id == "tYYY" || id == "tZZZ") next
2627
+ print
2628
+ }
2629
+ '
2630
+ }
2631
+
2632
+ # t2434: Insert content_file into target_file immediately after the closing
2633
+ # "-->" of the named TOON marker block (<!--TOON:<tag>...-->).
2634
+ # Idempotent only in the sense that each call inserts once per marker; repeated
2635
+ # calls would stack insertions. Intended to be called once per tag per upgrade.
2636
+ _insert_after_toon_marker() {
2637
+ local target_file="$1" toon_tag="$2" content_file="$3"
2638
+ local temp_file="${target_file}.insert"
2639
+ local marker_open="<!--TOON:${toon_tag}"
2640
+ local in_marker=false
2641
+ while IFS= read -r line || [[ -n "$line" ]]; do
2642
+ [[ "$line" == *"$marker_open"* ]] && in_marker=true
2643
+ if [[ "$in_marker" == true && "$line" == "-->" ]]; then
2644
+ echo "$line"
2645
+ echo ""
2646
+ cat "$content_file"
2647
+ in_marker=false
2648
+ continue
2649
+ fi
2650
+ echo "$line"
2651
+ done <"$target_file" >"$temp_file"
2652
+ mv "$temp_file" "$target_file"
2653
+ }
2654
+
2655
+ # t2434: Preserve each of the 6 task sections into $workdir/<tag>.txt for
2656
+ # later re-insertion after the template is applied. Placeholder filter runs
2657
+ # per section so Format-block tXXX-style examples never reach the new file.
2658
+ _upgrade_todo_preserve_sections() {
2659
+ local todo_file="$1" workdir="$2"
2660
+ local sections=("Ready" "Backlog" "In Progress" "In Review" "Done" "Declined")
2661
+ local tags=("ready" "backlog" "in_progress" "in_review" "done" "declined")
2662
+ local i=0
2663
+ while [[ $i -lt ${#sections[@]} ]]; do
2664
+ local section="${sections[$i]}" tag="${tags[$i]}"
2665
+ local content
2666
+ content=$(_extract_todo_section "$todo_file" "$section")
2667
+ if [[ -n "$content" ]]; then
2668
+ content=$(printf '%s\n' "$content" | _filter_todo_placeholders)
2669
+ [[ -n "$content" ]] && printf '%s\n' "$content" >"$workdir/${tag}.txt"
2670
+ fi
2671
+ i=$((i + 1))
2672
+ done
2673
+ return 0
2674
+ }
2675
+
2676
+ # t2434: Re-insert preserved section content after its matching TOON marker
2677
+ # in the freshly-applied new template. Caller is responsible for counting
2678
+ # merged tasks from the final file — keeping count out of the hot loop avoids
2679
+ # subshell/arithmetic edge cases under `set -u` when content contains `GH#`-
2680
+ # style IDs that don't match a naive `t[0-9]` count pattern.
2681
+ _upgrade_todo_reinsert_sections() {
2682
+ local todo_file="$1" workdir="$2"
2683
+ local tags=("ready" "backlog" "in_progress" "in_review" "done" "declined")
2684
+ local tag content_file
2685
+ for tag in "${tags[@]}"; do
2686
+ content_file="$workdir/${tag}.txt"
2687
+ [[ -f "$content_file" && -s "$content_file" ]] || continue
2688
+ grep -q "<!--TOON:${tag}" "$todo_file" || continue
2689
+ _insert_after_toon_marker "$todo_file" "$tag" "$content_file"
2690
+ done
2691
+ return 0
2692
+ }
2693
+
2694
+ # t2434: Upgrade TODO.md to the latest TOON-enhanced template, preserving
2695
+ # tasks from all 6 sections (Ready, Backlog, In Progress, In Review, Done,
2696
+ # Declined). Prior behaviour (GH#20077) only preserved Backlog and silently
2697
+ # dropped the other 5 sections into TODO.md.bak, losing audit-trail data.
2588
2698
  _upgrade_todo() {
2589
2699
  local todo_file="$1" todo_template="$2" backup="$3"
2590
2700
  print_info "Upgrading TODO.md..."
2591
- local existing_tasks=""
2701
+ local workdir=""
2702
+ workdir=$(mktemp -d)
2703
+ # shellcheck disable=SC2064 # intentional $workdir expansion at trap-set time
2704
+ trap "rm -rf \"${workdir}\"" RETURN
2592
2705
  if [[ -f "$todo_file" ]]; then
2593
- # Extract everything under ## Backlog (tasks AND ### subsection headers)
2594
- # until the next ## header or EOF — preserves semantic grouping.
2595
- # GH#17804: Skip ## Format section and filter out template placeholder IDs
2596
- # (tXXX, tYYY, tZZZ) that are documentation examples, not real tasks.
2597
- existing_tasks=$(awk '
2598
- # Section-aware: track when inside ## Format to skip its content
2599
- /^## Format/ { in_format=1; next }
2600
- in_format && /^## / { in_format=0 }
2601
- in_format { next }
2602
- # Also skip content inside markdown code blocks (``` fenced blocks)
2603
- /^```/ { in_codeblock = !in_codeblock; next }
2604
- in_codeblock { next }
2605
- # Extract from ## Backlog to next ## header
2606
- /^## Backlog/ { found=1; next }
2607
- found && /^## / { exit }
2608
- found
2609
- ' "$todo_file" 2>/dev/null || echo "")
2610
- # GH#17804: Filter out lines with non-numeric task IDs (template placeholders
2611
- # like tXXX, tYYY, tZZZ). Real task IDs match t<digits> or t<digits>.<digits>.
2612
- if [[ -n "$existing_tasks" ]]; then
2613
- existing_tasks=$(printf '%s\n' "$existing_tasks" | awk '
2614
- # Keep non-task lines (subsection headers, comments, blank lines)
2615
- !/^- \[[ x-]\] t/ { print; next }
2616
- # For task lines: extract the ID and validate it is numeric
2617
- {
2618
- id = $0
2619
- sub(/^- \[[ x-]\] /, "", id)
2620
- sub(/ .*/, "", id)
2621
- # Valid IDs: t followed by digits, optionally .digits (subtasks)
2622
- if (id ~ /^t[0-9]+(\.[0-9]+)*$/) print
2623
- }
2624
- ')
2625
- fi
2706
+ _upgrade_todo_preserve_sections "$todo_file" "$workdir"
2626
2707
  [[ "$backup" == "true" ]] && {
2627
2708
  cp "$todo_file" "${todo_file}.bak"
2628
2709
  print_success "Backup created: TODO.md.bak"
@@ -2636,27 +2717,11 @@ _upgrade_todo() {
2636
2717
  cp "$todo_template" "$todo_file"
2637
2718
  fi
2638
2719
  sed_inplace "s/{{DATE}}/$(date +%Y-%m-%d)/" "$todo_file" 2>/dev/null || true
2639
- if [[ -n "$existing_tasks" ]] && grep -q "<!--TOON:backlog" "$todo_file"; then
2640
- local temp_file="${todo_file}.merge" tasks_file
2641
- tasks_file=$(mktemp)
2642
- trap 'rm -f "${tasks_file:-}"' RETURN
2643
- printf '%s\n' "$existing_tasks" >"$tasks_file"
2644
- local in_backlog=false
2645
- while IFS= read -r line || [[ -n "$line" ]]; do
2646
- [[ "$line" == *"<!--TOON:backlog"* ]] && in_backlog=true
2647
- if [[ "$in_backlog" == true && "$line" == "-->" ]]; then
2648
- echo "$line"
2649
- echo ""
2650
- cat "$tasks_file"
2651
- in_backlog=false
2652
- continue
2653
- fi
2654
- echo "$line"
2655
- done <"$todo_file" >"$temp_file"
2656
- rm -f "$tasks_file"
2657
- mv "$temp_file" "$todo_file"
2658
- print_success "Merged existing tasks into Backlog"
2659
- fi
2720
+ _upgrade_todo_reinsert_sections "$todo_file" "$workdir"
2721
+ local merged=0
2722
+ merged=$(grep -cE '^- \[[ x-]\] (t[0-9]|GH#[0-9])' "$todo_file" 2>/dev/null || true)
2723
+ merged="${merged:-0}"
2724
+ [[ "$merged" -gt 0 ]] && print_success "Merged $merged existing task(s) across sections"
2660
2725
  print_success "TODO.md upgraded to TOON-enhanced template"
2661
2726
  return 0
2662
2727
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "3.8.81",
3
+ "version": "3.8.84",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "bin": {
package/setup.sh CHANGED
@@ -12,7 +12,7 @@ shopt -s inherit_errexit 2>/dev/null || true
12
12
  # AI Assistant Server Access Framework Setup Script
13
13
  # Helps developers set up the framework for their infrastructure
14
14
  #
15
- # Version: 3.8.81
15
+ # Version: 3.8.84
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)