aidevops 3.15.1 → 3.15.3

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 +67 -1
  3. package/package.json +1 -1
  4. package/setup.sh +130 -15
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.15.1
1
+ 3.15.3
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.15.1
8
+ # Version: 3.15.3
9
9
 
10
10
  set -euo pipefail
11
11
 
@@ -749,11 +749,76 @@ cmd_detect() {
749
749
  return 0
750
750
  }
751
751
 
752
+ _cmd_setup_help() {
753
+ printf '%s\n' "Usage: aidevops setup --scope <scope>"
754
+ printf '%s\n' ""
755
+ printf '%s\n' "Scopes:"
756
+ printf '%s\n' " opencode Repair/install the OpenCode CLI only"
757
+ printf '%s\n' " agents Deploy aidevops agents/scripts only"
758
+ printf '%s\n' " hooks Install safety hooks only"
759
+ printf '%s\n' " tabby Sync Tabby terminal profiles only"
760
+ printf '%s\n' " pulse Install/refresh the pulse scheduler only"
761
+ printf '%s\n' " full Run ./setup.sh --non-interactive"
762
+ return 0
763
+ }
764
+
765
+ cmd_setup() {
766
+ local scope=""
767
+ while [[ $# -gt 0 ]]; do
768
+ local arg="$1"
769
+ case "$arg" in
770
+ --scope)
771
+ if [[ -z "${2:-}" ]]; then
772
+ print_error "--scope requires a value"
773
+ _cmd_setup_help
774
+ return 1
775
+ fi
776
+ scope="$2"
777
+ shift 2
778
+ ;;
779
+ --scope=*)
780
+ scope="${arg#--scope=}"
781
+ shift
782
+ ;;
783
+ help | --help | -h)
784
+ _cmd_setup_help
785
+ return 0
786
+ ;;
787
+ *)
788
+ print_error "Unknown setup option: $arg"
789
+ _cmd_setup_help
790
+ return 1
791
+ ;;
792
+ esac
793
+ done
794
+
795
+ if [[ -z "$scope" ]]; then
796
+ print_error "Missing required --scope value"
797
+ _cmd_setup_help
798
+ return 1
799
+ fi
800
+
801
+ local setup_script="${INSTALL_DIR}/setup.sh"
802
+ if [[ ! -f "$setup_script" ]]; then
803
+ print_error "setup.sh not found at $setup_script"
804
+ return 1
805
+ fi
806
+
807
+ if [[ "$scope" == "full" ]]; then
808
+ bash "$setup_script" --non-interactive
809
+ return $?
810
+ fi
811
+
812
+ bash "$setup_script" --stage "$scope"
813
+ return $?
814
+ }
815
+
752
816
 
753
817
  # Help text helpers (extracted for complexity reduction)
754
818
  _help_commands() {
755
819
  echo "Commands:"
756
820
  echo " init [features] Initialize aidevops in current project"
821
+ echo " setup --scope <s> Run scoped setup/deploy (opencode, agents, hooks, tabby, pulse, full)"
757
822
  echo " init-routines Scaffold private routines repo (--org <name> | --local)"
758
823
  echo " upgrade-planning Upgrade TODO.md/PLANS.md to latest templates"
759
824
  echo " features List available features for init"
@@ -1408,6 +1473,7 @@ main() {
1408
1473
  shift || true
1409
1474
  case "$command" in
1410
1475
  init | i) cmd_init "$@" ;;
1476
+ setup) cmd_setup "$@" ;;
1411
1477
  features | f) cmd_features ;;
1412
1478
  status | s) cmd_status ;;
1413
1479
  update | upgrade | u) cmd_update "$@" ;;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "3.15.1",
3
+ "version": "3.15.3",
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.15.1
15
+ # Version: 3.15.3
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)
@@ -31,6 +31,13 @@ CLEAN_MODE=false
31
31
  INTERACTIVE_MODE=false
32
32
  NON_INTERACTIVE="${AIDEVOPS_NON_INTERACTIVE:-false}"
33
33
  UPDATE_TOOLS_MODE=false
34
+ SETUP_STAGE=""
35
+ SETUP_STAGE_OPENCODE="setup_opencode_cli"
36
+ SETUP_STAGE_AGENTS="deploy_aidevops_agents"
37
+ SETUP_STAGE_HOOKS="setup_safety_hooks"
38
+ SETUP_STAGE_TABBY="setup_tabby"
39
+ SETUP_STAGE_PULSE="setup_supervisor_pulse"
40
+ SETUP_OS_DARWIN="Darwin"
34
41
  # Python compatibility floor used by setup checks and skill/tool gating.
35
42
  # Keep in sync with .agents/scripts/setup/modules/plugins.sh requirements.
36
43
  PYTHON_REQUIRED_MAJOR=3
@@ -38,7 +45,7 @@ PYTHON_REQUIRED_MINOR=10
38
45
  export PYTHON_REQUIRED_MAJOR PYTHON_REQUIRED_MINOR
39
46
  # Platform constants — exported for sourced .agents/scripts/setup/modules (shell-env.sh,
40
47
  # tool-install.sh) that reference them at runtime.
41
- PLATFORM_MACOS=$([[ "$(uname -s)" == "Darwin" ]] && echo true || echo false)
48
+ PLATFORM_MACOS=$([[ "$(uname -s)" == "$SETUP_OS_DARWIN" ]] && echo true || echo false)
42
49
  PLATFORM_ARM64=$([[ "$(uname -m)" == "arm64" || "$(uname -m)" == "aarch64" ]] && echo true || echo false)
43
50
  export PLATFORM_MACOS PLATFORM_ARM64
44
51
  readonly PLATFORM_MACOS PLATFORM_ARM64
@@ -236,7 +243,7 @@ if [[ ! -d "$_setup_script_dir/.agents/scripts/setup/modules" ]]; then
236
243
 
237
244
  # Auto-install git if missing
238
245
  if ! command -v git >/dev/null 2>&1; then
239
- if [[ "$(uname)" == "Darwin" ]]; then
246
+ if [[ "$(uname)" == "$SETUP_OS_DARWIN" ]]; then
240
247
  print_info "Installing Xcode Command Line Tools (includes git)..."
241
248
  xcode-select --install 2>/dev/null || true
242
249
  xcode_wait=0
@@ -346,6 +353,26 @@ parse_args() {
346
353
  UPDATE_TOOLS_MODE=true
347
354
  shift
348
355
  ;;
356
+ --stage)
357
+ if [[ -z "${2:-}" ]]; then
358
+ print_error "--stage requires a value"
359
+ _setup_print_stage_help
360
+ exit 1
361
+ fi
362
+ SETUP_STAGE="$2"
363
+ NON_INTERACTIVE=true
364
+ shift 2
365
+ ;;
366
+ --stage=*)
367
+ SETUP_STAGE="${_opt#--stage=}"
368
+ if [[ -z "$SETUP_STAGE" ]]; then
369
+ print_error "--stage requires a value"
370
+ _setup_print_stage_help
371
+ exit 1
372
+ fi
373
+ NON_INTERACTIVE=true
374
+ shift
375
+ ;;
349
376
  --help | -h)
350
377
  echo "Usage: ./setup.sh [OPTIONS]"
351
378
  echo ""
@@ -353,6 +380,7 @@ parse_args() {
353
380
  echo " --clean Remove stale files before deploying (cleans ~/.aidevops/agents/)"
354
381
  echo " --interactive, -i Ask confirmation before each step"
355
382
  echo " --non-interactive, -n Deploy agents only, skip all optional installs (no prompts)"
383
+ echo " --stage <name> Run one supported setup stage/scope without full setup"
356
384
  echo " --update, -u Check for and offer to update outdated tools after setup"
357
385
  echo " --help Show this help message"
358
386
  echo ""
@@ -360,6 +388,8 @@ parse_args() {
360
388
  echo "Use --clean after removing or renaming agents to sync deletions."
361
389
  echo "Use --interactive to control each step individually."
362
390
  echo "Use --non-interactive for CI/CD or AI agent shells (no stdin required)."
391
+ echo "Use --stage for targeted updates: opencode, agents, hooks, tabby, pulse, full."
392
+ echo "Stage aliases: ${SETUP_STAGE_OPENCODE}, ${SETUP_STAGE_AGENTS}, ${SETUP_STAGE_HOOKS}, ${SETUP_STAGE_TABBY}, ${SETUP_STAGE_PULSE}."
363
393
  echo "Use --update to check for tool updates after setup completes."
364
394
  exit 0
365
395
  ;;
@@ -370,9 +400,47 @@ parse_args() {
370
400
  ;;
371
401
  esac
372
402
  done
403
+ if [[ -n "$SETUP_STAGE" ]]; then
404
+ _setup_validate_stage "$SETUP_STAGE" || exit $?
405
+ fi
406
+ return 0
407
+ }
408
+
409
+ _setup_print_stage_help() {
410
+ printf '%s\n' "Supported setup stages/scopes:"
411
+ printf ' opencode | %s Repair/install OpenCode CLI only\n' "$SETUP_STAGE_OPENCODE"
412
+ printf ' agents | %s Deploy .agents scripts/prompts only\n' "$SETUP_STAGE_AGENTS"
413
+ printf ' hooks | %s Install safety hooks only\n' "$SETUP_STAGE_HOOKS"
414
+ printf ' tabby | %s Sync Tabby profiles only\n' "$SETUP_STAGE_TABBY"
415
+ printf ' pulse | %s Install/refresh pulse scheduler only\n' "$SETUP_STAGE_PULSE"
416
+ printf '%s\n' " full Run the default full setup path"
417
+ return 0
418
+ }
419
+
420
+ _setup_canonical_stage() {
421
+ local stage="$1"
422
+ case "$stage" in
423
+ opencode | "$SETUP_STAGE_OPENCODE") printf '%s' "$SETUP_STAGE_OPENCODE" ;;
424
+ agents | "$SETUP_STAGE_AGENTS") printf '%s' "$SETUP_STAGE_AGENTS" ;;
425
+ hooks | "$SETUP_STAGE_HOOKS") printf '%s' "$SETUP_STAGE_HOOKS" ;;
426
+ tabby | "$SETUP_STAGE_TABBY") printf '%s' "$SETUP_STAGE_TABBY" ;;
427
+ pulse | "$SETUP_STAGE_PULSE") printf '%s' "$SETUP_STAGE_PULSE" ;;
428
+ full) printf '%s' "full" ;;
429
+ *) return 1 ;;
430
+ esac
373
431
  return 0
374
432
  }
375
433
 
434
+ _setup_validate_stage() {
435
+ local stage="$1"
436
+ if _setup_canonical_stage "$stage" >/dev/null; then
437
+ return 0
438
+ fi
439
+ print_error "Unknown setup stage/scope: $stage"
440
+ _setup_print_stage_help
441
+ return 1
442
+ }
443
+
376
444
  # Initialize ~/.config/aidevops/settings.json with documented defaults.
377
445
  # Idempotent — merges missing keys without overwriting existing values.
378
446
  init_settings_json() {
@@ -614,7 +682,7 @@ _setup_lock_pid_is_noninteractive_setup() {
614
682
  [[ "$pid" =~ ^[0-9]+$ ]] || return 1
615
683
  owner_args=$(ps -p "$pid" -o args= 2>/dev/null || true)
616
684
  [[ -n "$owner_args" ]] || return 0
617
- [[ "$owner_args" == *"setup.sh"* && "$owner_args" == *"--non-interactive"* ]]
685
+ [[ "$owner_args" == *"setup.sh"* && ( "$owner_args" == *"--non-interactive"* || "$owner_args" == *"--stage"* ) ]]
618
686
  return $?
619
687
  }
620
688
 
@@ -628,7 +696,7 @@ _setup_lock_dir_age_seconds() {
628
696
  fi
629
697
  if type _file_mtime_epoch >/dev/null 2>&1; then
630
698
  lock_mtime=$(_file_mtime_epoch "$lock_dir" 2>/dev/null || true)
631
- elif [[ "$(uname -s 2>/dev/null || true)" == "Darwin" || "$(uname -s 2>/dev/null || true)" == "FreeBSD" ]]; then
699
+ elif [[ "$(uname -s 2>/dev/null || true)" == "$SETUP_OS_DARWIN" || "$(uname -s 2>/dev/null || true)" == "FreeBSD" ]]; then
632
700
  lock_mtime=$(stat -f %m "$lock_dir" 2>/dev/null || true)
633
701
  else
634
702
  lock_mtime=$(stat -c %Y "$lock_dir" 2>/dev/null || true)
@@ -1002,9 +1070,7 @@ _setup_acquire_noninteractive_setup_lock() {
1002
1070
  # GH#21060 / t2911: Every direct function call is wrapped with _time_step so
1003
1071
  # that a one-line-per-stage TSV timing record is appended to
1004
1072
  # $HOME/.aidevops/logs/setup-stage-timings.log for post-run diagnostics.
1005
- _setup_run_non_interactive() {
1006
- print_info "Non-interactive mode: deploying agents and running safe migrations only"
1007
-
1073
+ _setup_init_stage_timing_log() {
1008
1074
  # GH#21060: Initialise per-stage timing log; rotate if over 10K lines / 1MB.
1009
1075
  local _stl
1010
1076
  _stl="$HOME/.aidevops/logs/setup-stage-timings.log"
@@ -1021,6 +1087,51 @@ _setup_run_non_interactive() {
1021
1087
  print_info "setup-stage-timings.log rotated (was ${_stl_lines} lines / ${_stl_bytes} bytes)"
1022
1088
  fi
1023
1089
  fi
1090
+ return 0
1091
+ }
1092
+
1093
+ _setup_run_scoped_stage() {
1094
+ local os="$1"
1095
+ local stage
1096
+ stage="$(_setup_canonical_stage "$SETUP_STAGE")" || return 1
1097
+
1098
+ if [[ "$stage" == "full" ]]; then
1099
+ _setup_run_non_interactive
1100
+ _setup_post_setup_steps "$os"
1101
+ return 0
1102
+ fi
1103
+
1104
+ print_info "Scoped setup mode: running ${stage} only"
1105
+ _setup_init_stage_timing_log
1106
+ case "$stage" in
1107
+ "$SETUP_STAGE_OPENCODE")
1108
+ _time_step "$SETUP_STAGE_OPENCODE" setup_opencode_cli
1109
+ ;;
1110
+ "$SETUP_STAGE_AGENTS")
1111
+ _time_step "$SETUP_STAGE_AGENTS" deploy_aidevops_agents
1112
+ _time_step "_deploy_hotfix_config" _deploy_hotfix_config
1113
+ ;;
1114
+ "$SETUP_STAGE_HOOKS")
1115
+ _time_step "$SETUP_STAGE_HOOKS" setup_safety_hooks
1116
+ ;;
1117
+ "$SETUP_STAGE_TABBY")
1118
+ _time_step "$SETUP_STAGE_TABBY" setup_tabby
1119
+ ;;
1120
+ "$SETUP_STAGE_PULSE")
1121
+ _time_step "$SETUP_STAGE_PULSE" setup_supervisor_pulse "$os"
1122
+ ;;
1123
+ *)
1124
+ print_error "Unsupported canonical setup stage: $stage"
1125
+ return 1
1126
+ ;;
1127
+ esac
1128
+ return 0
1129
+ }
1130
+
1131
+ _setup_run_non_interactive() {
1132
+ print_info "Non-interactive mode: deploying agents and running safe migrations only"
1133
+
1134
+ _setup_init_stage_timing_log
1024
1135
 
1025
1136
  _time_step "protect_current_setup_worktree" protect_current_setup_worktree
1026
1137
  _time_step "verify_location" verify_location
@@ -1051,16 +1162,16 @@ _setup_run_non_interactive() {
1051
1162
  # collision with @anthropic-ai/claude-code or similar). Skipping this
1052
1163
  # in non-interactive mode is the bug PR #20189 introduced and what
1053
1164
  # alex-solovyev's runner spam stemmed from.
1054
- _time_step "setup_opencode_cli" setup_opencode_cli
1165
+ _time_step "$SETUP_STAGE_OPENCODE" setup_opencode_cli
1055
1166
  _time_step "validate_opencode_config" validate_opencode_config
1056
- _time_step "deploy_aidevops_agents" deploy_aidevops_agents
1167
+ _time_step "$SETUP_STAGE_AGENTS" deploy_aidevops_agents
1057
1168
  _time_step "_setup_install_pulse_plist_early" _setup_install_pulse_plist_early
1058
1169
  _time_step "_deploy_hotfix_config" _deploy_hotfix_config
1059
1170
  _time_step "sync_agent_sources" sync_agent_sources
1060
1171
  _time_step "install_aidevops_cli" install_aidevops_cli
1061
1172
  _time_step "setup_shellcheck_wrapper" setup_shellcheck_wrapper
1062
1173
  if is_feature_enabled safety_hooks 2>/dev/null; then
1063
- _time_step "setup_safety_hooks" setup_safety_hooks
1174
+ _time_step "$SETUP_STAGE_HOOKS" setup_safety_hooks
1064
1175
  fi
1065
1176
  _time_step "init_settings_json" init_settings_json
1066
1177
 
@@ -1248,7 +1359,7 @@ _setup_noninteractive_schedulers() {
1248
1359
  # Auto-update handles non-interactive internally (systemd detection fixed in GH#17861)
1249
1360
  _time_step "setup_auto_update" setup_auto_update
1250
1361
  if _should_setup_noninteractive_supervisor_pulse; then
1251
- _time_step "setup_supervisor_pulse" setup_supervisor_pulse "$os"
1362
+ _time_step "$SETUP_STAGE_PULSE" setup_supervisor_pulse "$os"
1252
1363
  fi
1253
1364
  # t2939: pulse-watchdog (independent revival mechanism). Always installed
1254
1365
  # alongside the pulse — it is a no-op when pulse is disabled. Skipping the
@@ -1308,7 +1419,7 @@ _setup_noninteractive_schedulers() {
1308
1419
  _time_step "setup_opencode_db_maintenance" setup_opencode_db_maintenance
1309
1420
  # Migrate cron entries to systemd after schedulers are installed (GH#17695 Finding D)
1310
1421
  _time_step "migrate_cron_to_systemd" migrate_cron_to_systemd
1311
- _time_step "setup_tabby" setup_tabby
1422
+ _time_step "$SETUP_STAGE_TABBY" setup_tabby
1312
1423
  return 0
1313
1424
  }
1314
1425
 
@@ -1469,13 +1580,17 @@ main() {
1469
1580
  # never blocks setup even if bash install fails.
1470
1581
  _setup_check_bash_upgrade
1471
1582
 
1472
- if [[ "$NON_INTERACTIVE" == "true" ]]; then
1583
+ if [[ -n "$SETUP_STAGE" ]]; then
1584
+ _setup_run_scoped_stage "$_os"
1585
+ elif [[ "$NON_INTERACTIVE" == "true" ]]; then
1473
1586
  _setup_run_non_interactive
1474
1587
  else
1475
1588
  _setup_run_interactive
1476
1589
  fi
1477
1590
 
1478
- _setup_post_setup_steps "$_os"
1591
+ if [[ -z "$SETUP_STAGE" ]]; then
1592
+ _setup_post_setup_steps "$_os"
1593
+ fi
1479
1594
 
1480
1595
  _setup_restart_pulse_if_running
1481
1596