aidevops 3.13.42 → 3.13.43
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/VERSION +1 -1
- package/aidevops.sh +1 -1
- package/package.json +1 -1
- package/setup-modules/agent-deploy.sh +96 -28
- package/setup-modules/migrations.sh +55 -17
- package/setup.sh +40 -21
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.13.
|
|
1
|
+
3.13.43
|
package/aidevops.sh
CHANGED
package/package.json
CHANGED
|
@@ -391,11 +391,34 @@ _atomic_stage_and_deploy_agents() {
|
|
|
391
391
|
fi
|
|
392
392
|
done
|
|
393
393
|
|
|
394
|
-
# Atomic swap: mv is atomic on the same filesystem (POSIX rename())
|
|
394
|
+
# Atomic swap: mv is atomic on the same filesystem (POSIX rename()).
|
|
395
|
+
# IMPORTANT: explicit error checks are REQUIRED here because this function
|
|
396
|
+
# is called via `|| return 1` which disables set -e inside the function
|
|
397
|
+
# body (bash set -e semantics: disabled in any function called as part of
|
|
398
|
+
# a compound list such as `fn || ...`). Without these checks, a failed mv
|
|
399
|
+
# falls through silently, the backup is deleted, and the function returns
|
|
400
|
+
# 0 with $target_dir absent — the root cause of GH#22014 where worktree
|
|
401
|
+
# setup left ~/.aidevops/agents missing while reporting [SETUP_COMPLETE].
|
|
395
402
|
if [[ -d "$target_dir" ]]; then
|
|
396
|
-
mv "$target_dir" "$old_dir"
|
|
403
|
+
if ! mv "$target_dir" "$old_dir"; then
|
|
404
|
+
print_error "Failed to move live agents to backup ($old_dir) — agents directory preserved"
|
|
405
|
+
rm -rf "$staging_dir"
|
|
406
|
+
return 1
|
|
407
|
+
fi
|
|
408
|
+
fi
|
|
409
|
+
if ! mv "$staging_dir" "$target_dir"; then
|
|
410
|
+
print_error "Failed to move staging to live agents directory — attempting rollback"
|
|
411
|
+
# Restore the previous agents dir from backup so the system stays functional.
|
|
412
|
+
if [[ -d "$old_dir" ]]; then
|
|
413
|
+
if mv "$old_dir" "$target_dir"; then
|
|
414
|
+
print_info "Rollback successful — previous agents directory restored"
|
|
415
|
+
else
|
|
416
|
+
print_error "Rollback failed — agents directory is missing! Previous state preserved in $old_dir"
|
|
417
|
+
fi
|
|
418
|
+
fi
|
|
419
|
+
rm -rf "$staging_dir"
|
|
420
|
+
return 1
|
|
397
421
|
fi
|
|
398
|
-
mv "$staging_dir" "$target_dir"
|
|
399
422
|
rm -rf "$old_dir"
|
|
400
423
|
return 0
|
|
401
424
|
}
|
|
@@ -503,6 +526,9 @@ _deploy_agents_post_copy() {
|
|
|
503
526
|
# (those edits are overwritten by every deploy). Emits a warning listing drifted
|
|
504
527
|
# files and the canonical source path to edit instead.
|
|
505
528
|
# Non-fatal: always returns 0 so deployment proceeds.
|
|
529
|
+
#
|
|
530
|
+
# Performance: uses a single rsync --checksum --dry-run call instead of one
|
|
531
|
+
# diff -q subprocess per script (was 783 calls → now 1 call; t3221).
|
|
506
532
|
_warn_deployed_script_drift() {
|
|
507
533
|
local source_dir="$1"
|
|
508
534
|
local target_dir="$2"
|
|
@@ -512,20 +538,35 @@ _warn_deployed_script_drift() {
|
|
|
512
538
|
if [[ ! -d "$source_scripts" || ! -d "$target_scripts" ]]; then
|
|
513
539
|
return 0
|
|
514
540
|
fi
|
|
515
|
-
if ! command -v diff &>/dev/null; then
|
|
516
|
-
return 0
|
|
517
|
-
fi
|
|
518
541
|
|
|
519
542
|
local -a drifted=()
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
local
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
543
|
+
if command -v rsync &>/dev/null; then
|
|
544
|
+
# Single bulk comparison: rsync --checksum --dry-run reports changed files
|
|
545
|
+
# without transferring anything. --out-format='%f' prints only the relative
|
|
546
|
+
# path of each changed file. Filter to top-level *.sh only (no subdirs).
|
|
547
|
+
local changed_file
|
|
548
|
+
while IFS= read -r changed_file; do
|
|
549
|
+
[[ -n "$changed_file" ]] || continue
|
|
550
|
+
# Skip subdirectory scripts (only warn about top-level scripts/)
|
|
551
|
+
[[ "$changed_file" == */* ]] && continue
|
|
552
|
+
[[ "$changed_file" == *.sh ]] || continue
|
|
553
|
+
drifted+=("$changed_file")
|
|
554
|
+
done < <(rsync --checksum --dry-run \
|
|
555
|
+
--out-format='%f' \
|
|
556
|
+
--include='*.sh' --exclude='*/' --exclude='*' \
|
|
557
|
+
"$source_scripts/" "$target_scripts/" 2>/dev/null || true)
|
|
558
|
+
elif command -v diff &>/dev/null; then
|
|
559
|
+
# Fallback: one diff -q per script (slow, only reached when rsync absent)
|
|
560
|
+
local f bn
|
|
561
|
+
for f in "$target_scripts"/*.sh; do
|
|
562
|
+
[[ -f "$f" ]] || continue
|
|
563
|
+
bn=$(basename "$f")
|
|
564
|
+
local src="$source_scripts/$bn"
|
|
565
|
+
if [[ -f "$src" ]] && ! diff -q "$src" "$f" &>/dev/null; then
|
|
566
|
+
drifted+=("$bn")
|
|
567
|
+
fi
|
|
568
|
+
done
|
|
569
|
+
fi
|
|
529
570
|
|
|
530
571
|
if [[ ${#drifted[@]} -gt 0 ]]; then
|
|
531
572
|
print_warning "Deployed scripts differ from canonical source (local edits will be overwritten; backup will be created):"
|
|
@@ -577,9 +618,18 @@ deploy_aidevops_agents() {
|
|
|
577
618
|
_warn_deployed_script_drift "$source_dir" "$target_dir"
|
|
578
619
|
fi
|
|
579
620
|
|
|
580
|
-
# Create backup if target exists (with rotation)
|
|
621
|
+
# Create backup if target exists (with rotation).
|
|
622
|
+
# Skip when the deployed SHA matches the current HEAD — nothing changed on
|
|
623
|
+
# disk, so there is nothing worth backing up (t3221: steady-state perf).
|
|
581
624
|
if [[ -d "$target_dir" ]]; then
|
|
582
|
-
|
|
625
|
+
local _cur_sha _dep_sha
|
|
626
|
+
_cur_sha=$(git -C "$repo_dir" rev-parse HEAD 2>/dev/null || echo "")
|
|
627
|
+
_dep_sha=$(cat "${HOME}/.aidevops/.deployed-sha" 2>/dev/null || echo "")
|
|
628
|
+
if [[ -n "$_cur_sha" && -n "$_dep_sha" && "$_cur_sha" == "$_dep_sha" ]]; then
|
|
629
|
+
print_info "No changes since last deploy (${_cur_sha:0:8}) — skipping backup"
|
|
630
|
+
else
|
|
631
|
+
create_backup_with_rotation "$target_dir" "agents"
|
|
632
|
+
fi
|
|
583
633
|
fi
|
|
584
634
|
|
|
585
635
|
mkdir -p "$target_dir"
|
|
@@ -591,20 +641,24 @@ deploy_aidevops_agents() {
|
|
|
591
641
|
_atomic_stage_and_deploy_agents "$source_dir" "$target_dir" || return 1
|
|
592
642
|
fi
|
|
593
643
|
|
|
644
|
+
# Postcondition: verify the swap actually produced a functional agents dir.
|
|
645
|
+
# _atomic_stage_and_deploy_agents returns 0 on success, but a belt-and-
|
|
646
|
+
# suspenders check here catches any future regression where the function
|
|
647
|
+
# might return early without correctly populating $target_dir (GH#22014).
|
|
648
|
+
if [[ ! -d "$target_dir/scripts" ]]; then
|
|
649
|
+
print_error "Deploy verification failed: $target_dir/scripts missing after swap"
|
|
650
|
+
print_error "The agents directory was not correctly deployed — setup cannot continue"
|
|
651
|
+
return 1
|
|
652
|
+
fi
|
|
653
|
+
|
|
594
654
|
print_success "Deployed agents to $target_dir"
|
|
595
655
|
_deploy_agents_post_copy "$target_dir" "$repo_dir" "$source_dir" "$plugins_file"
|
|
596
656
|
|
|
597
|
-
#
|
|
598
|
-
#
|
|
599
|
-
#
|
|
600
|
-
#
|
|
601
|
-
#
|
|
602
|
-
# were correct but the running pulse kept using old code in memory.
|
|
603
|
-
_restart_pulse_if_running
|
|
604
|
-
|
|
605
|
-
# Write deployed-SHA stamp so aidevops-update-check.sh can detect
|
|
606
|
-
# script drift between this deploy and future canonical-repo commits.
|
|
607
|
-
# Written AFTER pulse restart so the stamp reflects a fully-applied deploy.
|
|
657
|
+
# Write deployed-SHA stamp BEFORE the pulse restart so the stamp is
|
|
658
|
+
# available immediately for subsequent setup steps and the next run's
|
|
659
|
+
# backup-skip check (t3221). Previously written after the blocking
|
|
660
|
+
# restart wait; moving it here has no correctness impact — the deploy
|
|
661
|
+
# is already fully on disk at this point.
|
|
608
662
|
# t2156: enables auto-redeploy when local commits land between releases.
|
|
609
663
|
local deployed_sha
|
|
610
664
|
deployed_sha=$(git -C "$repo_dir" rev-parse HEAD 2>/dev/null || echo "")
|
|
@@ -614,6 +668,20 @@ deploy_aidevops_agents() {
|
|
|
614
668
|
printf '%s\n' "$deployed_sha" >"${aidevops_dir}/.deployed-sha"
|
|
615
669
|
fi
|
|
616
670
|
|
|
671
|
+
# Restart pulse in the background — bash processes load source files at
|
|
672
|
+
# startup and don't re-read them when files change on disk. Without a
|
|
673
|
+
# restart, fixes to pulse-*.sh, dispatch-dedup-*.sh, and other sourced
|
|
674
|
+
# scripts don't take effect until the next manual restart.
|
|
675
|
+
#
|
|
676
|
+
# t3221: running this asynchronously saves the 10-15s blocking wait
|
|
677
|
+
# (pkill + up to 10s die-wait + sleep 5 launchd grace period). The
|
|
678
|
+
# deploy is already complete on disk; the pulse picks up the new scripts
|
|
679
|
+
# once it restarts regardless of when that happens relative to setup.sh
|
|
680
|
+
# finishing. disown prevents SIGHUP propagation if setup.sh is sourced
|
|
681
|
+
# interactively; in script mode the orphan survives the exit anyway.
|
|
682
|
+
_restart_pulse_if_running &
|
|
683
|
+
disown
|
|
684
|
+
|
|
617
685
|
return 0
|
|
618
686
|
}
|
|
619
687
|
|
|
@@ -616,7 +616,16 @@ _migrate_ai_config_agent_refs() {
|
|
|
616
616
|
# 3. .gitignore entries in user projects
|
|
617
617
|
# 4. References in user's AI assistant configs
|
|
618
618
|
# 5. References in ~/.aidevops/ config files
|
|
619
|
+
#
|
|
620
|
+
# Guarded by a sentinel file: on a converged system the function does
|
|
621
|
+
# a repos.json scan and a find(1) scan of ~/Git, both of which cost
|
|
622
|
+
# several seconds per run (t3221).
|
|
619
623
|
migrate_agent_to_agents_folder() {
|
|
624
|
+
local _sentinel="${HOME}/.aidevops/.migrations/agent-to-agents-done"
|
|
625
|
+
if [[ -f "$_sentinel" ]]; then
|
|
626
|
+
return 0
|
|
627
|
+
fi
|
|
628
|
+
|
|
620
629
|
print_info "Checking for .agent -> .agents migration..."
|
|
621
630
|
|
|
622
631
|
local migrated=0
|
|
@@ -649,6 +658,9 @@ migrate_agent_to_agents_folder() {
|
|
|
649
658
|
print_info "No .agent -> .agents migration needed"
|
|
650
659
|
fi
|
|
651
660
|
|
|
661
|
+
# Write sentinel so subsequent setup runs skip the repos+find scans (t3221)
|
|
662
|
+
mkdir -p "$(dirname "$_sentinel")"
|
|
663
|
+
date -u +%Y-%m-%dT%H:%M:%SZ >"$_sentinel"
|
|
652
664
|
return 0
|
|
653
665
|
}
|
|
654
666
|
|
|
@@ -782,6 +794,12 @@ _migrate_mcp_npx_to_binary() {
|
|
|
782
794
|
|
|
783
795
|
# Remove deprecated MCP entries from opencode.json
|
|
784
796
|
# These MCPs have been replaced by curl-based subagents (zero context cost)
|
|
797
|
+
#
|
|
798
|
+
# The one-time cleanup (remove deprecated entries + migrate npx→binary) is
|
|
799
|
+
# guarded by a versioned sentinel (t3221). Bump the sentinel version when new
|
|
800
|
+
# deprecated MCPs are added to _remove_deprecated_mcp_entries.
|
|
801
|
+
# The recurring update_mcp_paths_in_opencode call is NOT guarded — it resolves
|
|
802
|
+
# stale binary paths on every run (paths can change after package upgrades).
|
|
785
803
|
cleanup_deprecated_mcps() {
|
|
786
804
|
local opencode_config
|
|
787
805
|
opencode_config=$(find_opencode_config) || return 0
|
|
@@ -794,27 +812,36 @@ cleanup_deprecated_mcps() {
|
|
|
794
812
|
return 0
|
|
795
813
|
fi
|
|
796
814
|
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
815
|
+
# One-time cleanup: remove deprecated MCPs and migrate npx→binary paths.
|
|
816
|
+
# Sentinel version must be bumped whenever new deprecated MCPs are added.
|
|
817
|
+
local _sentinel="${HOME}/.aidevops/.migrations/cleanup-deprecated-mcps-v1"
|
|
818
|
+
if [[ ! -f "$_sentinel" ]]; then
|
|
819
|
+
local cleaned=0
|
|
820
|
+
local tmp_config
|
|
821
|
+
tmp_config=$(mktemp)
|
|
822
|
+
trap 'rm -f "${tmp_config:-}"' RETURN
|
|
801
823
|
|
|
802
|
-
|
|
824
|
+
cp "$opencode_config" "$tmp_config"
|
|
803
825
|
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
826
|
+
# Remove deprecated MCP and tool entries
|
|
827
|
+
_remove_deprecated_mcp_entries "$tmp_config"
|
|
828
|
+
cleaned=$((cleaned + _cleanup_count))
|
|
807
829
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
830
|
+
# Migrate npx/pipx commands to full binary paths (faster startup, PATH-independent)
|
|
831
|
+
_migrate_mcp_npx_to_binary "$tmp_config"
|
|
832
|
+
cleaned=$((cleaned + _cleanup_count))
|
|
811
833
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
834
|
+
if [[ $cleaned -gt 0 ]]; then
|
|
835
|
+
create_backup_with_rotation "$opencode_config" "opencode"
|
|
836
|
+
mv "$tmp_config" "$opencode_config"
|
|
837
|
+
print_info "Updated $cleaned MCP entry/entries in opencode.json (using full binary paths)"
|
|
838
|
+
else
|
|
839
|
+
rm -f "$tmp_config"
|
|
840
|
+
fi
|
|
841
|
+
|
|
842
|
+
# Write sentinel
|
|
843
|
+
mkdir -p "$(dirname "$_sentinel")"
|
|
844
|
+
date -u +%Y-%m-%dT%H:%M:%SZ >"$_sentinel"
|
|
818
845
|
fi
|
|
819
846
|
|
|
820
847
|
# Always resolve bare binary names to full paths (fixes PATH-dependent startup)
|
|
@@ -1127,7 +1154,15 @@ migrate_old_backups() {
|
|
|
1127
1154
|
# Migrate loop state from .claude/ to .agents/loop-state/ in user projects
|
|
1128
1155
|
# Also migrates from legacy .agents/loop-state/ to .agents/loop-state/
|
|
1129
1156
|
# The migration is non-destructive: moves files, doesn't delete originals until confirmed
|
|
1157
|
+
#
|
|
1158
|
+
# Guarded by a sentinel file: on a converged system the function does a
|
|
1159
|
+
# find(1) scan of ~/Git which costs several seconds per run (t3221).
|
|
1130
1160
|
migrate_loop_state_directories() {
|
|
1161
|
+
local _sentinel="${HOME}/.aidevops/.migrations/loop-state-dirs-migrated"
|
|
1162
|
+
if [[ -f "$_sentinel" ]]; then
|
|
1163
|
+
return 0
|
|
1164
|
+
fi
|
|
1165
|
+
|
|
1131
1166
|
print_info "Checking for legacy loop state directories..."
|
|
1132
1167
|
|
|
1133
1168
|
local migrated=0
|
|
@@ -1218,6 +1253,9 @@ migrate_loop_state_directories() {
|
|
|
1218
1253
|
print_info "No legacy loop state directories found"
|
|
1219
1254
|
fi
|
|
1220
1255
|
|
|
1256
|
+
# Write sentinel so subsequent setup runs skip the find scan (t3221)
|
|
1257
|
+
mkdir -p "$(dirname "$_sentinel")"
|
|
1258
|
+
date -u +%Y-%m-%dT%H:%M:%SZ >"$_sentinel"
|
|
1221
1259
|
return 0
|
|
1222
1260
|
}
|
|
1223
1261
|
|
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.
|
|
15
|
+
# Version: 3.13.43
|
|
16
16
|
#
|
|
17
17
|
# Quick Install:
|
|
18
18
|
# npm install -g aidevops && aidevops update (recommended)
|
|
@@ -152,6 +152,13 @@ _cron_escape() {
|
|
|
152
152
|
_time_step() {
|
|
153
153
|
local _ts_stage="$1"
|
|
154
154
|
shift
|
|
155
|
+
# GH#22012: In non-interactive mode, emit the stage name before running so
|
|
156
|
+
# an operator watching setup.sh output can identify which step is blocking.
|
|
157
|
+
# The TSV log entry below is written AFTER the step returns — it provides no
|
|
158
|
+
# signal during a hang. This print is the only in-flight indicator.
|
|
159
|
+
if [[ "${NON_INTERACTIVE:-false}" == "true" ]]; then
|
|
160
|
+
printf '[SETUP] stage: %s\n' "$_ts_stage"
|
|
161
|
+
fi
|
|
155
162
|
local _ts_start _ts_end _ts_duration _ts_exit
|
|
156
163
|
_ts_start=$(date +%s.%N 2>/dev/null || date +%s)
|
|
157
164
|
_ts_exit=0
|
|
@@ -1355,70 +1362,74 @@ _setup_run_interactive() {
|
|
|
1355
1362
|
_setup_noninteractive_schedulers() {
|
|
1356
1363
|
local os="$1"
|
|
1357
1364
|
|
|
1365
|
+
# GH#22012: Wrap every scheduler step with _time_step so the stage-timing
|
|
1366
|
+
# log ($HOME/.aidevops/logs/setup-stage-timings.log) covers post-deploy
|
|
1367
|
+
# scheduler setup — the same visibility _setup_run_non_interactive has.
|
|
1368
|
+
|
|
1358
1369
|
# Auto-update handles non-interactive internally (systemd detection fixed in GH#17861)
|
|
1359
|
-
setup_auto_update
|
|
1370
|
+
_time_step "setup_auto_update" setup_auto_update
|
|
1360
1371
|
if _should_setup_noninteractive_supervisor_pulse; then
|
|
1361
|
-
setup_supervisor_pulse "$os"
|
|
1372
|
+
_time_step "setup_supervisor_pulse" setup_supervisor_pulse "$os"
|
|
1362
1373
|
fi
|
|
1363
1374
|
# t2939: pulse-watchdog (independent revival mechanism). Always installed
|
|
1364
1375
|
# alongside the pulse — it is a no-op when pulse is disabled. Skipping the
|
|
1365
1376
|
# `_should_setup_noninteractive_*` guard intentionally: this is layered
|
|
1366
1377
|
# defense, the cost of installing it is one plist file, and the user opts
|
|
1367
1378
|
# in by enabling the pulse itself.
|
|
1368
|
-
setup_pulse_watchdog "${PULSE_ENABLED:-}"
|
|
1379
|
+
_time_step "setup_pulse_watchdog" setup_pulse_watchdog "${PULSE_ENABLED:-}"
|
|
1369
1380
|
# Regenerate other schedulers if already installed (GH#17695 Finding B).
|
|
1370
1381
|
# Stats wrapper is a pulse dependency — also install on first run when
|
|
1371
1382
|
# the supervisor pulse is consented (t2418, GH#20016).
|
|
1372
1383
|
if _should_setup_noninteractive_stats_wrapper; then
|
|
1373
|
-
setup_stats_wrapper "${PULSE_ENABLED:-}"
|
|
1384
|
+
_time_step "setup_stats_wrapper" setup_stats_wrapper "${PULSE_ENABLED:-}"
|
|
1374
1385
|
fi
|
|
1375
1386
|
if _should_setup_noninteractive_scheduler "Failure miner" "sh.aidevops.routine-gh-failure-miner" "aidevops: gh-failure-miner" "aidevops-gh-failure-miner"; then
|
|
1376
|
-
setup_failure_miner "${PULSE_ENABLED:-}"
|
|
1387
|
+
_time_step "setup_failure_miner" setup_failure_miner "${PULSE_ENABLED:-}"
|
|
1377
1388
|
fi
|
|
1378
1389
|
if _should_setup_noninteractive_scheduler "Process guard" "sh.aidevops.process-guard" "aidevops: process-guard" "aidevops-process-guard"; then
|
|
1379
|
-
setup_process_guard
|
|
1390
|
+
_time_step "setup_process_guard" setup_process_guard
|
|
1380
1391
|
fi
|
|
1381
1392
|
if _should_setup_noninteractive_scheduler "Memory pressure" "sh.aidevops.memory-pressure-monitor" "aidevops: memory-pressure-monitor" "aidevops-memory-pressure-monitor"; then
|
|
1382
|
-
setup_memory_pressure_monitor
|
|
1393
|
+
_time_step "setup_memory_pressure_monitor" setup_memory_pressure_monitor
|
|
1383
1394
|
fi
|
|
1384
1395
|
if _should_setup_noninteractive_scheduler "Screen time" "sh.aidevops.screen-time-snapshot" "aidevops: screen-time-snapshot" "aidevops-screen-time-snapshot"; then
|
|
1385
|
-
setup_screen_time_snapshot
|
|
1396
|
+
_time_step "setup_screen_time_snapshot" setup_screen_time_snapshot
|
|
1386
1397
|
fi
|
|
1387
1398
|
if _should_setup_noninteractive_scheduler "Contribution watch" "sh.aidevops.contribution-watch" "aidevops: contribution-watch" "aidevops-contribution-watch"; then
|
|
1388
|
-
setup_contribution_watch
|
|
1399
|
+
_time_step "setup_contribution_watch" setup_contribution_watch
|
|
1389
1400
|
fi
|
|
1390
1401
|
# t2903 (#21049): complexity scan — extracted from pulse dispatch preflight
|
|
1391
1402
|
if _should_setup_noninteractive_scheduler "Complexity scan" "sh.aidevops.complexity-scan" "aidevops: complexity-scan" "aidevops-complexity-scan"; then
|
|
1392
|
-
setup_complexity_scan
|
|
1403
|
+
_time_step "setup_complexity_scan" setup_complexity_scan
|
|
1393
1404
|
fi
|
|
1394
1405
|
# t2862 (GH#20919): pulse merge routine — fast 120s standalone merge pass.
|
|
1395
1406
|
# t3036 (GH#21616): use the pulse-dependency escape hatch instead of the
|
|
1396
1407
|
# generic chicken-and-egg gate so the routine installs on existing systems
|
|
1397
1408
|
# whenever the supervisor pulse is consented.
|
|
1398
1409
|
if _should_setup_noninteractive_pulse_merge_routine; then
|
|
1399
|
-
setup_pulse_merge_routine
|
|
1410
|
+
_time_step "setup_pulse_merge_routine" setup_pulse_merge_routine
|
|
1400
1411
|
fi
|
|
1401
1412
|
# t2932 (GH#21125): peer productivity monitor — adaptive cross-runner
|
|
1402
1413
|
# dispatch coordination, runs every 30 min.
|
|
1403
1414
|
if _should_setup_noninteractive_scheduler "Peer productivity monitor" "sh.aidevops.peer-productivity-monitor" "aidevops: peer-productivity-monitor" "aidevops-peer-productivity-monitor"; then
|
|
1404
|
-
setup_peer_productivity_monitor
|
|
1415
|
+
_time_step "setup_peer_productivity_monitor" setup_peer_productivity_monitor
|
|
1405
1416
|
fi
|
|
1406
1417
|
# Repo sync handles non-interactive mode internally (systemd detection fixed in GH#17861)
|
|
1407
|
-
setup_repo_sync
|
|
1418
|
+
_time_step "setup_repo_sync" setup_repo_sync
|
|
1408
1419
|
# r914 repo-aidevops-health — daily drift keeper (t2366)
|
|
1409
|
-
setup_repo_aidevops_health
|
|
1420
|
+
_time_step "setup_repo_aidevops_health" setup_repo_aidevops_health
|
|
1410
1421
|
if _should_setup_noninteractive_scheduler "Profile README" "sh.aidevops.profile-readme-update" "aidevops: profile-readme-update" "aidevops-profile-readme-update"; then
|
|
1411
|
-
setup_profile_readme
|
|
1422
|
+
_time_step "setup_profile_readme" setup_profile_readme
|
|
1412
1423
|
fi
|
|
1413
1424
|
if _should_setup_noninteractive_scheduler "OAuth token refresh" "sh.aidevops.token-refresh" "aidevops: token-refresh" "aidevops-token-refresh"; then
|
|
1414
|
-
setup_oauth_token_refresh
|
|
1425
|
+
_time_step "setup_oauth_token_refresh" setup_oauth_token_refresh
|
|
1415
1426
|
fi
|
|
1416
1427
|
# opencode DB maintenance (r913, t2183). Helper self-noops on missing
|
|
1417
1428
|
# DB — safe to install unconditionally in non-interactive mode too.
|
|
1418
|
-
setup_opencode_db_maintenance
|
|
1429
|
+
_time_step "setup_opencode_db_maintenance" setup_opencode_db_maintenance
|
|
1419
1430
|
# Migrate cron entries to systemd after schedulers are installed (GH#17695 Finding D)
|
|
1420
|
-
migrate_cron_to_systemd
|
|
1421
|
-
setup_tabby
|
|
1431
|
+
_time_step "migrate_cron_to_systemd" migrate_cron_to_systemd
|
|
1432
|
+
_time_step "setup_tabby" setup_tabby
|
|
1422
1433
|
return 0
|
|
1423
1434
|
}
|
|
1424
1435
|
|
|
@@ -1551,9 +1562,17 @@ main() {
|
|
|
1551
1562
|
# No-op if pulse is not running, or if AIDEVOPS_SKIP_PULSE_RESTART=1.
|
|
1552
1563
|
# Uses the deployed helper (not the repo-local one) so the restart runs
|
|
1553
1564
|
# against the agents directory setup.sh just populated.
|
|
1565
|
+
# GH#22012: bounded 120 s timeout prevents setup.sh hanging here when the
|
|
1566
|
+
# pulse helper takes unusually long to stop a stalled instance. Falls back
|
|
1567
|
+
# to an unbounded call on platforms without timeout(1) (old macOS w/o
|
|
1568
|
+
# coreutils, embedded shells).
|
|
1554
1569
|
local _pulse_helper="${HOME}/.aidevops/agents/scripts/pulse-lifecycle-helper.sh"
|
|
1555
1570
|
if [[ -x "$_pulse_helper" ]]; then
|
|
1556
|
-
|
|
1571
|
+
if command -v timeout >/dev/null 2>&1; then
|
|
1572
|
+
timeout 120 "$_pulse_helper" restart-if-running || print_warning "Pulse restart failed (non-fatal)"
|
|
1573
|
+
else
|
|
1574
|
+
"$_pulse_helper" restart-if-running || print_warning "Pulse restart failed (non-fatal)"
|
|
1575
|
+
fi
|
|
1557
1576
|
fi
|
|
1558
1577
|
|
|
1559
1578
|
# GH#18492 / t2026: completion sentinel. Must be the last output of a
|