aidevops 3.12.0 → 3.13.0
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 +24 -3
- package/package.json +1 -1
- package/setup-modules/schedulers.sh +168 -3
- package/setup.sh +9 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.13.0
|
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
|
+
# Version: 3.13.0
|
|
9
9
|
|
|
10
10
|
set -euo pipefail
|
|
11
11
|
|
|
@@ -1825,9 +1825,24 @@ _cmd_email() {
|
|
|
1825
1825
|
;;
|
|
1826
1826
|
poll)
|
|
1827
1827
|
# Direct poll commands forwarded to email-poll-helper.sh
|
|
1828
|
-
|
|
1828
|
+
local poll_action="${1:-tick}"
|
|
1829
|
+
shift || true
|
|
1830
|
+
_dispatch_helper "$_EPH" "$_EPH" "$poll_action" "$@" ;;
|
|
1831
|
+
thread)
|
|
1832
|
+
# Thread lookup: email thread <message-id> [knowledge-root]
|
|
1833
|
+
local _ETH="email-thread-helper.sh"
|
|
1834
|
+
_dispatch_helper "$_ETH" "$_ETH" thread "$@" ;;
|
|
1835
|
+
build)
|
|
1836
|
+
# Thread rebuild: email build [knowledge-root] [--force]
|
|
1837
|
+
local _ETH2="email-thread-helper.sh"
|
|
1838
|
+
_dispatch_helper "$_ETH2" "$_ETH2" build "$@" ;;
|
|
1839
|
+
filter)
|
|
1840
|
+
# Filter rules: email filter tick|add|test|list [knowledge-root]
|
|
1841
|
+
local _EFH="email-filter-helper.sh"
|
|
1842
|
+
[[ $# -eq 0 ]] && set -- list
|
|
1843
|
+
_dispatch_helper "$_EFH" "$_EFH" "$@" ;;
|
|
1829
1844
|
*)
|
|
1830
|
-
echo "Usage: aidevops email <mailbox|poll> [subcommand]"
|
|
1845
|
+
echo "Usage: aidevops email <mailbox|poll|thread|build|filter> [subcommand]"
|
|
1831
1846
|
echo ""
|
|
1832
1847
|
echo "Email subcommands:"
|
|
1833
1848
|
echo " mailbox add Register a new IMAP mailbox (interactive)"
|
|
@@ -1836,6 +1851,12 @@ _cmd_email() {
|
|
|
1836
1851
|
echo " mailbox remove <id> Un-register a mailbox"
|
|
1837
1852
|
echo " poll tick Poll all mailboxes now (same as routine r044)"
|
|
1838
1853
|
echo " poll backfill <id> Backfill a mailbox from a given date"
|
|
1854
|
+
echo " thread <message-id> Look up thread by message-id"
|
|
1855
|
+
echo " build [--force] Rebuild thread index from email sources"
|
|
1856
|
+
echo " filter list List filter rules"
|
|
1857
|
+
echo " filter add Add a new filter rule (interactive)"
|
|
1858
|
+
echo " filter test <rule> Dry-run rule against last 50 sources"
|
|
1859
|
+
echo " filter tick Run filter pass (routine r045)"
|
|
1839
1860
|
;;
|
|
1840
1861
|
esac
|
|
1841
1862
|
return 0
|
package/package.json
CHANGED
|
@@ -14,6 +14,11 @@ PULSE_STALE_THRESHOLD_SECONDS=1800
|
|
|
14
14
|
# future cadence shift only touches one place.
|
|
15
15
|
CRON_HOURLY="0 * * * *"
|
|
16
16
|
|
|
17
|
+
# Cron expression: every minute. Shared by process-guard, memory-pressure
|
|
18
|
+
# monitor, and pulse-watchdog schedulers (cron's minimum granularity).
|
|
19
|
+
# Kept DRY for the same reason as CRON_HOURLY.
|
|
20
|
+
CRON_EVERY_MINUTE="* * * * *"
|
|
21
|
+
|
|
17
22
|
# Resolve the modern bash binary path for use in launchd ProgramArguments.
|
|
18
23
|
# Launchd bypasses the shebang when ProgramArguments specifies an explicit
|
|
19
24
|
# interpreter, so we must resolve the path at plist generation time.
|
|
@@ -668,7 +673,12 @@ ${_env_overrides_xml} </dict>
|
|
|
668
673
|
<key>RunAtLoad</key>
|
|
669
674
|
<true/>
|
|
670
675
|
<key>KeepAlive</key>
|
|
671
|
-
<
|
|
676
|
+
<dict>
|
|
677
|
+
<key>SuccessfulExit</key>
|
|
678
|
+
<false/>
|
|
679
|
+
</dict>
|
|
680
|
+
<key>ThrottleInterval</key>
|
|
681
|
+
<integer>30</integer>
|
|
672
682
|
</dict>
|
|
673
683
|
</plist>
|
|
674
684
|
PLIST
|
|
@@ -731,6 +741,161 @@ _install_pulse_launchd() {
|
|
|
731
741
|
return 0
|
|
732
742
|
}
|
|
733
743
|
|
|
744
|
+
# Generate the pulse-watchdog launchd plist XML content.
|
|
745
|
+
# Args: $1=label, $2=tick_script, $3=bash_bin
|
|
746
|
+
# Prints the complete plist XML to stdout.
|
|
747
|
+
#
|
|
748
|
+
# The watchdog is an independent launchd job that runs every 60s and revives
|
|
749
|
+
# pulse if it has been dead longer than (StartInterval + grace). Layered
|
|
750
|
+
# defense alongside the pulse plist's KeepAlive=<dict><SuccessfulExit=false>
|
|
751
|
+
# (auto-restart on crash) and StartInterval (scheduled cadence). Catches the
|
|
752
|
+
# "clean exit + lost launchd schedule" failure mode that no other layer covers.
|
|
753
|
+
# (t2939)
|
|
754
|
+
_generate_pulse_watchdog_plist_content() {
|
|
755
|
+
local watchdog_label="$1"
|
|
756
|
+
local tick_script="$2"
|
|
757
|
+
local bash_bin="$3"
|
|
758
|
+
|
|
759
|
+
local _xml_label _xml_tick _xml_bash _xml_home _xml_path
|
|
760
|
+
_xml_label=$(_xml_escape "$watchdog_label")
|
|
761
|
+
_xml_tick=$(_xml_escape "$tick_script")
|
|
762
|
+
_xml_bash=$(_xml_escape "$bash_bin")
|
|
763
|
+
_xml_home=$(_xml_escape "$HOME")
|
|
764
|
+
_xml_path=$(_xml_escape "$PATH")
|
|
765
|
+
|
|
766
|
+
cat <<PLIST
|
|
767
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
768
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
769
|
+
<plist version="1.0">
|
|
770
|
+
<dict>
|
|
771
|
+
<key>Label</key>
|
|
772
|
+
<string>${_xml_label}</string>
|
|
773
|
+
<key>ProgramArguments</key>
|
|
774
|
+
<array>
|
|
775
|
+
<string>${_xml_bash}</string>
|
|
776
|
+
<string>${_xml_tick}</string>
|
|
777
|
+
</array>
|
|
778
|
+
<key>StartInterval</key>
|
|
779
|
+
<integer>60</integer>
|
|
780
|
+
<key>StandardOutPath</key>
|
|
781
|
+
<string>${_xml_home}/.aidevops/logs/pulse-watchdog-launchd.log</string>
|
|
782
|
+
<key>StandardErrorPath</key>
|
|
783
|
+
<string>${_xml_home}/.aidevops/logs/pulse-watchdog-launchd.log</string>
|
|
784
|
+
<key>EnvironmentVariables</key>
|
|
785
|
+
<dict>
|
|
786
|
+
<key>PATH</key>
|
|
787
|
+
<string>${_xml_path}</string>
|
|
788
|
+
<key>HOME</key>
|
|
789
|
+
<string>${_xml_home}</string>
|
|
790
|
+
</dict>
|
|
791
|
+
<key>RunAtLoad</key>
|
|
792
|
+
<true/>
|
|
793
|
+
<key>KeepAlive</key>
|
|
794
|
+
<false/>
|
|
795
|
+
<key>ThrottleInterval</key>
|
|
796
|
+
<integer>30</integer>
|
|
797
|
+
</dict>
|
|
798
|
+
</plist>
|
|
799
|
+
PLIST
|
|
800
|
+
return 0
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
# Install the pulse-watchdog via launchd (macOS).
|
|
804
|
+
# t2939: independent revival mechanism — see _generate_pulse_watchdog_plist_content
|
|
805
|
+
# header for the layering rationale.
|
|
806
|
+
_install_pulse_watchdog_launchd() {
|
|
807
|
+
local watchdog_label="sh.aidevops.pulse-watchdog"
|
|
808
|
+
local tick_script="$HOME/.aidevops/agents/scripts/pulse-watchdog-tick.sh"
|
|
809
|
+
local watchdog_plist="$HOME/Library/LaunchAgents/${watchdog_label}.plist"
|
|
810
|
+
|
|
811
|
+
# Refuse to install if the tick script is missing — the watchdog would
|
|
812
|
+
# fire-and-fail every 60s, polluting logs without doing useful work.
|
|
813
|
+
if [[ ! -x "$tick_script" ]]; then
|
|
814
|
+
print_warning "Pulse watchdog tick script missing or non-executable: $tick_script"
|
|
815
|
+
return 1
|
|
816
|
+
fi
|
|
817
|
+
|
|
818
|
+
local _xml_bash_bin
|
|
819
|
+
_xml_bash_bin=$(_resolve_modern_bash)
|
|
820
|
+
|
|
821
|
+
local watchdog_plist_content
|
|
822
|
+
watchdog_plist_content=$(_generate_pulse_watchdog_plist_content "$watchdog_label" "$tick_script" "$_xml_bash_bin")
|
|
823
|
+
|
|
824
|
+
if [[ -z "$watchdog_plist_content" ]]; then
|
|
825
|
+
print_warning "Pulse watchdog plist generation produced empty content — skipping"
|
|
826
|
+
return 1
|
|
827
|
+
fi
|
|
828
|
+
|
|
829
|
+
# shell-portability: ignore next — _install_pulse_watchdog_launchd is macOS-only
|
|
830
|
+
if _launchd_install_if_changed "$watchdog_label" "$watchdog_plist" "$watchdog_plist_content"; then
|
|
831
|
+
print_info "Pulse watchdog enabled (launchd, every 60s)"
|
|
832
|
+
else
|
|
833
|
+
print_warning "Failed to load pulse watchdog LaunchAgent"
|
|
834
|
+
fi
|
|
835
|
+
return 0
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
# Install the pulse-watchdog via systemd (Linux).
|
|
839
|
+
# t2939: parallels _install_pulse_watchdog_launchd for systems with systemd --user.
|
|
840
|
+
_install_pulse_watchdog_systemd() {
|
|
841
|
+
local tick_script="$HOME/.aidevops/agents/scripts/pulse-watchdog-tick.sh"
|
|
842
|
+
local watchdog_systemd="aidevops-pulse-watchdog"
|
|
843
|
+
local watchdog_log="$HOME/.aidevops/logs/pulse-watchdog-launchd.log"
|
|
844
|
+
|
|
845
|
+
if [[ ! -x "$tick_script" ]]; then
|
|
846
|
+
print_warning "Pulse watchdog tick script missing or non-executable: $tick_script"
|
|
847
|
+
return 1
|
|
848
|
+
fi
|
|
849
|
+
|
|
850
|
+
# Reuse the standard scheduler installer (cron-fallback aware).
|
|
851
|
+
# StartInterval=60 maps to every-minute cron schedule.
|
|
852
|
+
# shell-portability: ignore next — _install_scheduler_linux is Linux-only
|
|
853
|
+
_install_scheduler_linux \
|
|
854
|
+
"$watchdog_systemd" \
|
|
855
|
+
"aidevops: pulse-watchdog" \
|
|
856
|
+
"$CRON_EVERY_MINUTE" \
|
|
857
|
+
"\"${tick_script}\"" \
|
|
858
|
+
"60" \
|
|
859
|
+
"$watchdog_log" \
|
|
860
|
+
"" \
|
|
861
|
+
"Pulse watchdog enabled (every 60s)" \
|
|
862
|
+
"Failed to install pulse watchdog scheduler" \
|
|
863
|
+
"true" \
|
|
864
|
+
"false"
|
|
865
|
+
return 0
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
# Setup the pulse-watchdog scheduler (parallels setup_supervisor_pulse).
|
|
869
|
+
# t2939: layered defense — only installs when supervisor pulse is enabled,
|
|
870
|
+
# since a watchdog without a pulse to watch is a no-op every 60s.
|
|
871
|
+
#
|
|
872
|
+
# Args: $1 = pulse effective state ("true"/"false")
|
|
873
|
+
setup_pulse_watchdog() {
|
|
874
|
+
local _pulse_effective="$1"
|
|
875
|
+
local watchdog_label="sh.aidevops.pulse-watchdog"
|
|
876
|
+
local watchdog_systemd="aidevops-pulse-watchdog"
|
|
877
|
+
|
|
878
|
+
if [[ "$_pulse_effective" != "true" ]]; then
|
|
879
|
+
# Pulse disabled — uninstall the watchdog if present.
|
|
880
|
+
_uninstall_scheduler \
|
|
881
|
+
"$(uname -s)" \
|
|
882
|
+
"$watchdog_label" \
|
|
883
|
+
"$watchdog_systemd" \
|
|
884
|
+
"aidevops: pulse-watchdog" \
|
|
885
|
+
"Pulse watchdog disabled (pulse is off)"
|
|
886
|
+
return 0
|
|
887
|
+
fi
|
|
888
|
+
|
|
889
|
+
mkdir -p "$HOME/.aidevops/logs"
|
|
890
|
+
|
|
891
|
+
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
892
|
+
_install_pulse_watchdog_launchd
|
|
893
|
+
else
|
|
894
|
+
_install_pulse_watchdog_systemd
|
|
895
|
+
fi
|
|
896
|
+
return 0
|
|
897
|
+
}
|
|
898
|
+
|
|
734
899
|
# Check if systemd user services are available on this Linux system.
|
|
735
900
|
# Returns 0 if systemd --user is functional, 1 otherwise.
|
|
736
901
|
_systemd_user_available() {
|
|
@@ -1352,7 +1517,7 @@ GUARD_PLIST
|
|
|
1352
1517
|
_install_scheduler_linux \
|
|
1353
1518
|
"$guard_systemd" \
|
|
1354
1519
|
"aidevops: process-guard" \
|
|
1355
|
-
"
|
|
1520
|
+
"$CRON_EVERY_MINUTE" \
|
|
1356
1521
|
"\"${guard_script}\" kill-runaways" \
|
|
1357
1522
|
"30" \
|
|
1358
1523
|
"$guard_log" \
|
|
@@ -1444,7 +1609,7 @@ MONITOR_PLIST
|
|
|
1444
1609
|
_install_scheduler_linux \
|
|
1445
1610
|
"$monitor_systemd" \
|
|
1446
1611
|
"aidevops: memory-pressure-monitor" \
|
|
1447
|
-
"
|
|
1612
|
+
"$CRON_EVERY_MINUTE" \
|
|
1448
1613
|
"\"${monitor_script}\"" \
|
|
1449
1614
|
"60" \
|
|
1450
1615
|
"$monitor_log" \
|
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
|
+
# Version: 3.13.0
|
|
16
16
|
#
|
|
17
17
|
# Quick Install:
|
|
18
18
|
# npm install -g aidevops && aidevops update (recommended)
|
|
@@ -1246,6 +1246,12 @@ _setup_noninteractive_schedulers() {
|
|
|
1246
1246
|
if _should_setup_noninteractive_supervisor_pulse; then
|
|
1247
1247
|
setup_supervisor_pulse "$os"
|
|
1248
1248
|
fi
|
|
1249
|
+
# t2939: pulse-watchdog (independent revival mechanism). Always installed
|
|
1250
|
+
# alongside the pulse — it is a no-op when pulse is disabled. Skipping the
|
|
1251
|
+
# `_should_setup_noninteractive_*` guard intentionally: this is layered
|
|
1252
|
+
# defense, the cost of installing it is one plist file, and the user opts
|
|
1253
|
+
# in by enabling the pulse itself.
|
|
1254
|
+
setup_pulse_watchdog "${PULSE_ENABLED:-}"
|
|
1249
1255
|
# Regenerate other schedulers if already installed (GH#17695 Finding B).
|
|
1250
1256
|
# Stats wrapper is a pulse dependency — also install on first run when
|
|
1251
1257
|
# the supervisor pulse is consented (t2418, GH#20016).
|
|
@@ -1331,6 +1337,8 @@ _setup_post_setup_steps() {
|
|
|
1331
1337
|
# Post-setup: auto-update, schedulers, final instructions (GH#5793)
|
|
1332
1338
|
setup_auto_update
|
|
1333
1339
|
setup_supervisor_pulse "$os"
|
|
1340
|
+
# t2939: pulse-watchdog — independent revival mechanism, layered defense.
|
|
1341
|
+
setup_pulse_watchdog "${PULSE_ENABLED:-}"
|
|
1334
1342
|
setup_stats_wrapper "${PULSE_ENABLED:-}"
|
|
1335
1343
|
setup_failure_miner "${PULSE_ENABLED:-}"
|
|
1336
1344
|
setup_repo_sync
|