aidevops 3.13.76 → 3.13.78

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "3.13.76",
3
+ "version": "3.13.78",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,6 +57,7 @@
57
57
  "files": [
58
58
  "bin/",
59
59
  "aidevops.sh",
60
+ "aidevops-*-lib.sh",
60
61
  "setup.sh",
61
62
  "setup-modules/",
62
63
  "VERSION",
@@ -163,6 +163,23 @@ _deploy_agents_copy() {
163
163
  return 1
164
164
  }
165
165
 
166
+ # _is_reserved_agent_namespace namespace
167
+ # Returns 0 when a plugin namespace collides with a core aidevops agents
168
+ # directory. Such namespaces must never be passed as rsync/tar excludes because
169
+ # excluding scripts/ from the canonical source can deploy an agents tree that
170
+ # passes the copy step but fails the post-swap scripts/ invariant.
171
+ _is_reserved_agent_namespace() {
172
+ local namespace="$1"
173
+
174
+ case "$namespace" in
175
+ AGENTS.md|VERSION|advisories|commands|configs|custom|draft|hooks|plugins|prompts|reference|scripts|services|tools|workflows)
176
+ return 0
177
+ ;;
178
+ esac
179
+
180
+ return 1
181
+ }
182
+
166
183
  # _inject_plan_reminder target_dir
167
184
  # Injects the extracted OpenCode plan-reminder into Plan+ if the placeholder is present.
168
185
  _inject_plan_reminder() {
@@ -691,6 +708,10 @@ deploy_aidevops_agents() {
691
708
  local ns safe_ns
692
709
  while IFS= read -r ns; do
693
710
  if [[ -n "$ns" ]] && safe_ns=$(sanitize_plugin_namespace "$ns" 2>/dev/null); then
711
+ if _is_reserved_agent_namespace "$safe_ns"; then
712
+ print_warning "Skipping plugin namespace that collides with core agents directory: $safe_ns"
713
+ continue
714
+ fi
694
715
  plugin_namespaces+=("$safe_ns")
695
716
  fi
696
717
  done < <(jq -r '.plugins[].namespace // empty' "$plugins_file" 2>/dev/null)
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.13.76
15
+ # Version: 3.13.78
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)
@@ -1234,15 +1234,46 @@ _setup_register_child_pid() {
1234
1234
  return 0
1235
1235
  }
1236
1236
 
1237
+ _setup_collect_child_pids() {
1238
+ local parent_pid="$1"
1239
+ local child_pid=""
1240
+ local child_pids=""
1241
+ local current_pid="${BASHPID:-$$}"
1242
+ child_pids=$(pgrep -P "$parent_pid" 2>/dev/null || true)
1243
+ for child_pid in $child_pids; do
1244
+ [[ -n "$child_pid" && "$child_pid" != "$current_pid" ]] || continue
1245
+ printf '%s\n' "$child_pid"
1246
+ _setup_collect_child_pids "$child_pid"
1247
+ done
1248
+ return 0
1249
+ }
1250
+
1251
+ _setup_kill_pid_tree() {
1252
+ local signal_name="$1"
1253
+ local root_pid="$2"
1254
+ local child_pid=""
1255
+ local current_pid="${BASHPID:-$$}"
1256
+ [[ -n "$root_pid" && "$root_pid" != "$current_pid" ]] || return 0
1257
+ for child_pid in $(_setup_collect_child_pids "$root_pid"); do
1258
+ kill "-${signal_name}" "$child_pid" 2>/dev/null || true
1259
+ done
1260
+ kill "-${signal_name}" "$root_pid" 2>/dev/null || true
1261
+ return 0
1262
+ }
1263
+
1237
1264
  _setup_cleanup_noninteractive_children() {
1238
1265
  local pid=""
1266
+ local current_pid="${BASHPID:-$$}"
1239
1267
  local grace_s="${AIDEVOPS_SETUP_CHILD_TERM_GRACE_S:-2}"
1240
1268
  local has_live_child=false
1241
1269
  [[ "$grace_s" =~ ^[0-9]+$ ]] || grace_s=2
1270
+ for pid in $(_setup_collect_child_pids "$current_pid"); do
1271
+ _setup_register_child_pid "$pid"
1272
+ done
1242
1273
  for pid in ${SETUP_NONINTERACTIVE_CHILD_PIDS:-}; do
1243
1274
  if _setup_lock_pid_alive "$pid"; then
1244
1275
  has_live_child=true
1245
- kill -TERM "$pid" 2>/dev/null || true
1276
+ _setup_kill_pid_tree TERM "$pid"
1246
1277
  fi
1247
1278
  done
1248
1279
  if [[ "$has_live_child" == "true" && "$grace_s" -gt 0 ]]; then
@@ -1250,7 +1281,7 @@ _setup_cleanup_noninteractive_children() {
1250
1281
  fi
1251
1282
  for pid in ${SETUP_NONINTERACTIVE_CHILD_PIDS:-}; do
1252
1283
  if _setup_lock_pid_alive "$pid"; then
1253
- kill -KILL "$pid" 2>/dev/null || true
1284
+ _setup_kill_pid_tree KILL "$pid"
1254
1285
  fi
1255
1286
  done
1256
1287
  for pid in ${SETUP_NONINTERACTIVE_CHILD_PIDS:-}; do
@@ -1259,6 +1290,32 @@ _setup_cleanup_noninteractive_children() {
1259
1290
  return 0
1260
1291
  }
1261
1292
 
1293
+ _setup_run_noncritical_stage_bounded() {
1294
+ local stage_label="$1"
1295
+ local timeout_s="$2"
1296
+ shift 2
1297
+ local start_s=$SECONDS
1298
+ local pid=""
1299
+ local rc=0
1300
+ [[ "$timeout_s" =~ ^[0-9]+$ ]] || timeout_s=60
1301
+ "$@" &
1302
+ pid=$!
1303
+ _setup_register_child_pid "$pid"
1304
+ while _setup_lock_pid_alive "$pid"; do
1305
+ if (( SECONDS - start_s >= timeout_s )); then
1306
+ _setup_kill_pid_tree TERM "$pid"
1307
+ sleep "${AIDEVOPS_SETUP_CHILD_TERM_GRACE_S:-2}" 2>/dev/null || true
1308
+ _setup_kill_pid_tree KILL "$pid"
1309
+ wait "$pid" 2>/dev/null || true
1310
+ print_warning "${stage_label} exceeded ${timeout_s}s — skipping remaining non-critical work"
1311
+ return 0
1312
+ fi
1313
+ sleep 1
1314
+ done
1315
+ wait "$pid" 2>/dev/null || rc=$?
1316
+ return "$rc"
1317
+ }
1318
+
1262
1319
  _setup_release_noninteractive_setup_lock() {
1263
1320
  local lock_dir="${SETUP_NONINTERACTIVE_LOCK_DIR:-}"
1264
1321
  local owner_pid=""
@@ -1527,7 +1584,7 @@ _setup_run_non_interactive() {
1527
1584
  # files does not consume the remaining postflight budget and trip the outer
1528
1585
  # timeout (GH#22087). AIDEVOPS_DEPLOY_RUNTIMES_TIMEOUT controls the deadline.
1529
1586
  _time_step "deploy_agents_to_runtimes" _deploy_agents_to_runtimes_bounded
1530
- _time_step "update_opencode_config" update_opencode_config
1587
+ _time_step "update_opencode_config" _setup_run_noncritical_stage_bounded "OpenCode config update" "${AIDEVOPS_UPDATE_OPENCODE_CONFIG_TIMEOUT:-60}" update_opencode_config
1531
1588
  _time_step "update_claude_config" update_claude_config
1532
1589
  _time_step "update_codex_config" update_codex_config
1533
1590
  _time_step "update_cursor_config" update_cursor_config
@@ -1535,7 +1592,7 @@ _setup_run_non_interactive() {
1535
1592
  # Scaffold personal routines repo if not already present (idempotent).
1536
1593
  # Creates local git repo + private GitHub remote for personal repo only.
1537
1594
  # Org repos require explicit: aidevops init-routines --org <name>
1538
- _time_step "setup_routines" setup_routines
1595
+ _time_step "setup_routines" _setup_run_noncritical_stage_bounded "Routine setup" "${AIDEVOPS_SETUP_ROUTINES_TIMEOUT:-60}" setup_routines
1539
1596
  # Install/refresh the privacy-guard pre-push hook in every initialized
1540
1597
  # repo so TODO/todo/README/ISSUE_TEMPLATE pushes to public GitHub repos
1541
1598
  # are scanned for private slug leaks (t1968).
@@ -1723,7 +1780,7 @@ _setup_noninteractive_schedulers() {
1723
1780
  # generic chicken-and-egg gate so the routine installs on existing systems
1724
1781
  # whenever the supervisor pulse is consented.
1725
1782
  if _should_setup_noninteractive_pulse_merge_routine; then
1726
- _time_step "setup_pulse_merge_routine" setup_pulse_merge_routine
1783
+ _time_step "setup_pulse_merge_routine" _setup_run_noncritical_stage_bounded "Pulse merge routine setup" "${AIDEVOPS_SETUP_PULSE_MERGE_ROUTINE_TIMEOUT:-30}" setup_pulse_merge_routine
1727
1784
  fi
1728
1785
  # t2932 (GH#21125): peer productivity monitor — adaptive cross-runner
1729
1786
  # dispatch coordination, runs every 30 min.