feat: add idle-gated tool auto-update to keep all installed tools fresh#2145
feat: add idle-gated tool auto-update to keep all installed tools fresh#2145marcusquinn merged 3 commits intomainfrom
Conversation
Adds check_tool_freshness() to auto-update-helper.sh that runs tool-version-check.sh --update every 6 hours, but only when the user has been idle for 6+ hours (sleeping/away). Covers all npm, brew, and pip tools installed by setup.sh (OpenCode, gh, shellcheck, osgrep, etc). Cross-platform idle detection: - macOS: IOKit HIDIdleTime (works even over SSH) - Linux X11: xprintidle - Linux Wayland: dbus-send to GNOME ScreenSaver - Linux TTY/SSH: w(1) session idle parsing - Headless servers: always idle (no human at keyboard) Configurable via AIDEVOPS_TOOL_AUTO_UPDATE, AIDEVOPS_TOOL_FRESHNESS_HOURS, and AIDEVOPS_TOOL_IDLE_HOURS environment variables.
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. WalkthroughA new idle-gated tool freshness workflow has been integrated into the auto-update helper script. Cross-platform user idle detection and 6-hourly tool freshness checks execute only when idle thresholds are exceeded. State tracking persists tool update activity and timestamps, with integration points throughout cmd_check and cmd_status flows. Changes
Sequence Diagram(s)sequenceDiagram
participant User as User/System
participant Script as auto-update-helper.sh
participant StateFile as State File
participant ToolCheck as tool-version-check.sh
participant Status as Status Output
User->>Script: Trigger update flow (cmd_check)
Script->>Script: get_user_idle_seconds()
Script->>Script: Check TOOL_IDLE_HOURS threshold
alt User Idle Exceeds Threshold
Script->>StateFile: Check last_tool_check timestamp
StateFile-->>Script: Return last check time
alt 6+ Hours Since Last Check
Script->>ToolCheck: Invoke --update --quiet
ToolCheck-->>Script: Return update status
Script->>StateFile: update_tool_check_timestamp()
StateFile-->>Script: Persist last_tool_check & tool_updates_applied
else Within Freshness Window
Script->>Script: Skip tool update
end
else User Not Idle
Script->>Script: Skip idle-gated check
end
Script->>Status: cmd_status() with idle/update metrics
Status-->>User: Display last_tool_check, tool_updates_applied, idle time
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @marcusquinn, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces an intelligent auto-update mechanism for development tools, designed to keep the environment fresh without interrupting active user sessions. By leveraging cross-platform idle detection, it ensures that updates for various package managers are performed discreetly in the background, improving system maintenance and reducing manual overhead for users. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Sun Feb 22 15:51:42 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Code Review
The pull request introduces an idle-gated tool auto-update feature to auto-update-helper.sh, which is a valuable addition for maintaining tool freshness without disrupting active work. The implementation of cross-platform idle detection is comprehensive. However, the review identified several adherence issues with the repository's shell scripting rules, specifically regarding variable declarations and error suppression. Additionally, a potential bug related to octal interpretation in Bash arithmetic was found in the idle time parsing logic, which could lead to script errors when processing times with leading zeros.
| local parsed=0 | ||
| if [[ "$idle_field" =~ ^([0-9]+)days$ ]]; then | ||
| local d="${BASH_REMATCH[1]}" | ||
| parsed=$((d * 86400)) | ||
| elif [[ "$idle_field" =~ ^([0-9]+):([0-9]+)m$ ]]; then | ||
| # hours:minutes format (e.g. "23:15m") | ||
| local hh="${BASH_REMATCH[1]}" mm="${BASH_REMATCH[2]}" | ||
| parsed=$((hh * 3600 + mm * 60)) | ||
| elif [[ "$idle_field" =~ ^([0-9]+):([0-9]+)$ ]]; then | ||
| # minutes:seconds format (e.g. "3:42") | ||
| local mm="${BASH_REMATCH[1]}" ss="${BASH_REMATCH[2]}" | ||
| parsed=$((mm * 60 + ss)) | ||
| elif [[ "$idle_field" =~ ^([0-9]+)\.([0-9]+)s$ ]]; then | ||
| parsed="${BASH_REMATCH[1]}" | ||
| elif [[ "$idle_field" =~ ^([0-9]+)s$ ]]; then | ||
| parsed="${BASH_REMATCH[1]}" | ||
| fi |
There was a problem hiding this comment.
This block contains two issues:
- Octal Interpretation Bug: In Bash arithmetic
$(()), numbers with leading zeros (like08or09) are interpreted as octal. This will cause a syntax error ifwreturns times like08:42. Using the10#prefix forces base-10 interpretation. - Rule Violation: Local variables should be declared and assigned separately.
local parsed
parsed=0
if [[ "$idle_field" =~ ^([0-9]+)days$ ]]; then
local d
d="${BASH_REMATCH[1]}"
parsed=$((10#$d * 86400))
elif [[ "$idle_field" =~ ^([0-9]+):([0-9]+)m$ ]]; then
# hours:minutes format (e.g. "23:15m")
local hh mm
hh="${BASH_REMATCH[1]}"
mm="${BASH_REMATCH[2]}"
parsed=$((10#$hh * 3600 + 10#$mm * 60))
elif [[ "$idle_field" =~ ^([0-9]+):([0-9]+)$ ]]; then
# minutes:seconds format (e.g. "3:42")
local mm ss
mm="${BASH_REMATCH[1]}"
ss="${BASH_REMATCH[2]}"
parsed=$((10#$mm * 60 + 10#$ss))
elif [[ "$idle_field" =~ ^([0-9]+)\.([0-9]+)s$ ]]; then
parsed=$((10#${BASH_REMATCH[1]}))
elif [[ "$idle_field" =~ ^([0-9]+)s$ ]]; then
parsed=$((10#${BASH_REMATCH[1]}))
fiReferences
- When declaring and assigning local variables in shell scripts, separate the
localdeclaration from the assignment if command substitution is involved, to ensure exit code safety. For consistency, this pattern should be maintained even for simple assignments.
| local min_idle=999999 | ||
| local found_user=false | ||
| local idle_field |
There was a problem hiding this comment.
According to the repository rules, variables should be declared and assigned separately to ensure exit code safety and maintain consistency.
| local min_idle=999999 | |
| local found_user=false | |
| local idle_field | |
| local min_idle | |
| min_idle=999999 | |
| local found_user | |
| found_user=false | |
| local idle_field |
References
- When declaring and assigning local variables in shell scripts, separate the
localdeclaration from the assignment if command substitution is involved, to ensure exit code safety. For consistency, this pattern should be maintained even for simple assignments.
| [[ "$line" =~ ^USER ]] && continue | ||
| [[ "$line" =~ ^[[:space:]]*$ ]] && continue | ||
| # Extract idle field (5th column) | ||
| idle_field=$(echo "$line" | awk '{print $5}') |
There was a problem hiding this comment.
Calling awk inside a loop can be inefficient in shell scripts. Since the output of w is space-delimited, you can use the built-in read command to extract the required field more efficiently.
| idle_field=$(echo "$line" | awk '{print $5}') | |
| read -r _ _ _ _ idle_field _ <<< "$line" |
References
- In shell scripts, use pure Bash parameter expansion for string manipulations like calculating indentation within loops to avoid spawning subshells and improve performance.
| local freshness_hours="${AIDEVOPS_TOOL_FRESHNESS_HOURS:-$DEFAULT_TOOL_FRESHNESS_HOURS}" | ||
| if ! [[ "$freshness_hours" =~ ^[0-9]+$ ]] || [[ "$freshness_hours" -eq 0 ]]; then | ||
| log_warn "AIDEVOPS_TOOL_FRESHNESS_HOURS='${freshness_hours}' is not a positive integer — using default (${DEFAULT_TOOL_FRESHNESS_HOURS}h)" | ||
| freshness_hours="$DEFAULT_TOOL_FRESHNESS_HOURS" | ||
| fi | ||
| local freshness_seconds=$((freshness_hours * 3600)) | ||
|
|
||
| # Read last tool check timestamp from state file | ||
| local last_tool_check="" | ||
| if [[ -f "$STATE_FILE" ]] && command -v jq &>/dev/null; then | ||
| last_tool_check=$(jq -r '.last_tool_check // empty' "$STATE_FILE" 2>/dev/null || true) | ||
| fi | ||
|
|
||
| # Determine if check is needed (time gate) | ||
| local needs_check=true |
There was a problem hiding this comment.
Multiple local variables in this block are assigned during declaration, which violates the repository rules for variable declaration.
| local freshness_hours="${AIDEVOPS_TOOL_FRESHNESS_HOURS:-$DEFAULT_TOOL_FRESHNESS_HOURS}" | |
| if ! [[ "$freshness_hours" =~ ^[0-9]+$ ]] || [[ "$freshness_hours" -eq 0 ]]; then | |
| log_warn "AIDEVOPS_TOOL_FRESHNESS_HOURS='${freshness_hours}' is not a positive integer — using default (${DEFAULT_TOOL_FRESHNESS_HOURS}h)" | |
| freshness_hours="$DEFAULT_TOOL_FRESHNESS_HOURS" | |
| fi | |
| local freshness_seconds=$((freshness_hours * 3600)) | |
| # Read last tool check timestamp from state file | |
| local last_tool_check="" | |
| if [[ -f "$STATE_FILE" ]] && command -v jq &>/dev/null; then | |
| last_tool_check=$(jq -r '.last_tool_check // empty' "$STATE_FILE" 2>/dev/null || true) | |
| fi | |
| # Determine if check is needed (time gate) | |
| local needs_check=true | |
| local freshness_hours | |
| freshness_hours="${AIDEVOPS_TOOL_FRESHNESS_HOURS:-$DEFAULT_TOOL_FRESHNESS_HOURS}" | |
| if ! [[ "$freshness_hours" =~ ^[0-9]+$ ]] || [[ "$freshness_hours" -eq 0 ]]; then | |
| log_warn "AIDEVOPS_TOOL_FRESHNESS_HOURS='${freshness_hours}' is not a positive integer — using default (${DEFAULT_TOOL_FRESHNESS_HOURS}h)" | |
| freshness_hours="$DEFAULT_TOOL_FRESHNESS_HOURS" | |
| fi | |
| local freshness_seconds | |
| freshness_seconds=$((freshness_hours * 3600)) | |
| # Read last tool check timestamp from state file | |
| local last_tool_check | |
| last_tool_check="" | |
| if [[ -f "$STATE_FILE" ]] && command -v jq &>/dev/null; then | |
| last_tool_check=$(jq -r '.last_tool_check // empty' "$STATE_FILE" 2>/dev/null || true) | |
| fi | |
| # Determine if check is needed (time gate) | |
| local needs_check | |
| needs_check=true |
References
- When declaring and assigning local variables in shell scripts, separate the
localdeclaration from the assignment if command substitution is involved, to ensure exit code safety. For consistency, this pattern should be maintained even for simple assignments.
| local idle_hours="${AIDEVOPS_TOOL_IDLE_HOURS:-$DEFAULT_TOOL_IDLE_HOURS}" | ||
| if ! [[ "$idle_hours" =~ ^[0-9]+$ ]] || [[ "$idle_hours" -eq 0 ]]; then | ||
| log_warn "AIDEVOPS_TOOL_IDLE_HOURS='${idle_hours}' is not a positive integer — using default (${DEFAULT_TOOL_IDLE_HOURS}h)" | ||
| idle_hours="$DEFAULT_TOOL_IDLE_HOURS" | ||
| fi | ||
| local idle_threshold_seconds=$((idle_hours * 3600)) | ||
|
|
||
| local user_idle_seconds | ||
| user_idle_seconds=$(get_user_idle_seconds) | ||
| if [[ $user_idle_seconds -lt $idle_threshold_seconds ]]; then | ||
| local idle_h=$((user_idle_seconds / 3600)) | ||
| local idle_m=$(((user_idle_seconds % 3600) / 60)) | ||
| log_info "User idle ${idle_h}h${idle_m}m (need ${idle_hours}h) — deferring tool updates" | ||
| return 0 | ||
| fi | ||
|
|
||
| # Locate tool-version-check.sh | ||
| local tool_check_script="$HOME/.aidevops/agents/scripts/tool-version-check.sh" |
There was a problem hiding this comment.
Adhere to the repository rules by declaring and assigning local variables separately.
local idle_hours
idle_hours="${AIDEVOPS_TOOL_IDLE_HOURS:-$DEFAULT_TOOL_IDLE_HOURS}"
if ! [[ "$idle_hours" =~ ^[0-9]+$ ]] || [[ "$idle_hours" -eq 0 ]]; then
log_warn "AIDEVOPS_TOOL_IDLE_HOURS='${idle_hours}' is not a positive integer — using default (${DEFAULT_TOOL_IDLE_HOURS}h)"
idle_hours="$DEFAULT_TOOL_IDLE_HOURS"
fi
local idle_threshold_seconds
idle_threshold_seconds=$((idle_hours * 3600))
local user_idle_seconds
user_idle_seconds=$(get_user_idle_seconds)
if [[ $user_idle_seconds -lt $idle_threshold_seconds ]]; then
local idle_h
idle_h=$((user_idle_seconds / 3600))
local idle_m
idle_m=$(((user_idle_seconds % 3600) / 60))
log_info "User idle ${idle_h}h${idle_m}m (need ${idle_hours}h) — deferring tool updates"
return 0
fi
# Locate tool-version-check.sh
local tool_check_script
tool_check_script="$HOME/.aidevops/agents/scripts/tool-version-check.sh"References
- When declaring and assigning local variables in shell scripts, separate the
localdeclaration from the assignment if command substitution is involved, to ensure exit code safety. For consistency, this pattern should be maintained even for simple assignments.
| fi | ||
|
|
||
| # Count updates from output (best-effort: count lines with "Updated" or arrow) | ||
| local tool_updates=0 |
There was a problem hiding this comment.
Declare and assign separately per repository rules.
| local tool_updates=0 | |
| local tool_updates | |
| tool_updates=0 |
References
- When declaring and assigning local variables in shell scripts, separate the
localdeclaration from the assignment if command substitution is involved, to ensure exit code safety. For consistency, this pattern should be maintained even for simple assignments.
| # Args: $1 = number of tool updates applied (default: 0) | ||
| ####################################### | ||
| update_tool_check_timestamp() { | ||
| local updates_count="${1:-0}" |
There was a problem hiding this comment.
Declare and assign separately per repository rules.
| local updates_count="${1:-0}" | |
| local updates_count | |
| updates_count="${1:-0}" |
References
- When declaring and assigning local variables in shell scripts, separate the
localdeclaration from the assignment if command substitution is involved, to ensure exit code safety. For consistency, this pattern should be maintained even for simple assignments.
| --argjson count "$updates_count" \ | ||
| '. + {last_tool_check: $ts} | | ||
| .tool_updates_applied = ((.tool_updates_applied // 0) + $count)' \ | ||
| "$STATE_FILE" >"$tmp_state" 2>/dev/null && mv "$tmp_state" "$STATE_FILE" |
There was a problem hiding this comment.
The repository rules prohibit blanket suppression of errors with 2>/dev/null when jq is used, to ensure that actual syntax or system errors remain visible for debugging.
| "$STATE_FILE" >"$tmp_state" 2>/dev/null && mv "$tmp_state" "$STATE_FILE" | |
| "$STATE_FILE" >"$tmp_state" && mv "$tmp_state" "$STATE_FILE" |
References
- In shell scripts with 'set -e', use '|| true' to prevent the script from exiting when a command like 'jq' fails on an optional lookup. Do not suppress stderr with '2>/dev/null' so that actual syntax or system errors remain visible for debugging.
… loop efficiency - Fix octal interpretation bug: use 10# prefix for w(1) idle time parsing to handle leading zeros (e.g. '08:09' would fail as invalid octal) - Separate local variable declarations from assignments per repo conventions - Replace awk in w(1) parsing loop with read builtin for efficiency
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Sun Feb 22 15:57:14 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
.agents/scripts/auto-update-helper.sh (2)
389-465: Consider extracting the shared time-gate and timestamp-update patterns into helpers.The timestamp-parse + elapsed-check block and the
jq-based state-file update are duplicated three times acrosscheck_skill_freshness/check_openclaw_freshness/check_tool_freshnessand their correspondingupdate_*_check_timestampfunctions. A pair of helpers (e.g.,_is_freshness_elapsed <state_key> <threshold_secs>and_update_check_timestamp <state_key> <count>) would cut ~90 lines and make adding a fourth freshness gate trivial.Also applies to: 502-599, 713-810
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.agents/scripts/auto-update-helper.sh around lines 389 - 465, The code duplicates timestamp-parse/elapsed-check and jq-based state updates across check_skill_freshness, check_openclaw_freshness, check_tool_freshness and their update_*_check_timestamp helpers; extract that logic into two helpers (e.g., _is_freshness_elapsed <state_key> <threshold_secs> that reads STATE_FILE via jq, parses ISO timestamp into epoch (handle Darwin vs Linux using date), computes elapsed and returns 0/1 plus elapsed in a variable, and _update_check_timestamp <state_key> <count> that atomically updates/creates STATE_FILE with jq setting the key to current UTC ISO timestamp and an optional count field), then replace the duplicated blocks in check_skill_freshness (and the other check_* functions) to call _is_freshness_elapsed before running checks and call _update_check_timestamp at the end with the skill_updates value; keep existing log messages and feature flags (AIDEVOPS_SKILL_AUTO_UPDATE, AIDEVOPS_SKILL_FRESHNESS_HOURS) and continue to use skill-update-helper.sh invocation unchanged.
649-692:wfallback without-hmay setmin_idle=0due to the uptime header line.When
w -his unavailable and the fallbackw 2>/dev/nullruns, the first output line is the uptime summary (e.g.," 12:34 up 2 days, ..."). It doesn't match the^USERor blank-line guards, so it is processed:$5won't match any idle format leavingparsed=0, butfound_user=truegets set andmin_idledrops to0. The function then returns0(assume active), quietly suppressing tool updates on systems withoutw -hsupport.Since
w -his near-universal, this is low-risk, but a simple uptime-line guard would make the fallback more robust.♻️ Add an uptime header guard
while IFS= read -r line; do # Skip header lines [[ "$line" =~ ^USER ]] && continue [[ "$line" =~ ^[[:space:]]*$ ]] && continue + # Skip uptime summary line (starts with space + digit, e.g. " 12:34:56 up ...") + [[ "$line" =~ ^[[:space:]]+[0-9] ]] && continue # Extract idle field (5th column)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.agents/scripts/auto-update-helper.sh around lines 649 - 692, The loop parsing w output can treat the uptime summary line as a user line when w -h is missing, causing parsed to remain 0 and min_idle to be set to 0; inside the while read loop (which uses variables min_idle, found_user, idle_field, parsed), add a guard to skip uptime-summary lines before extracting idle_field — e.g. check and continue on lines matching the uptime pattern like ^[[:space:]]*[0-9]+:[0-9]+[[:space:]]+up (or containing " up " and "load average") so the uptime header is ignored and only real user lines set found_user and parsed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/scripts/auto-update-helper.sh:
- Around line 636-647: The dbus call is using
org.gnome.ScreenSaver.GetActiveTime which reports screensaver runtime rather
than session idle time; change the dbus-send invocation that currently calls
GetActiveTime to call GetSessionIdleTime and parse its numeric return into the
existing idle_secs variable (the dbus-send line and the awk that reads into
idle_secs), then keep the same validation (^[0-9]+$ and -gt 0) and echo/return
behavior so idle detection reflects true session idle time.
- Around line 796-800: The current command substitution for tool_updates
captures duplicate output when grep returns non-zero, producing "0\n0" and
breaking the numeric test; change the assignment so the grep -cE pipeline is
inside the substitution but the fallback runs outside it (e.g., run
tool_updates=$(echo "$update_output" | grep -cE '(Updated|→|->)' 2>/dev/null) ||
tool_updates=0) so that when set -o pipefail causes a non-match exit status the
external || handler assigns a clean 0; update the code that sets tool_updates
(referencing the variables tool_updates and update_output and the grep -cE
pipeline) and keep the redirected stderr 2>/dev/null as before.
- Around line 1242-1247: The echo block in cmd_status uses
idle_threshold="${AIDEVOPS_TOOL_IDLE_HOURS:-$DEFAULT_TOOL_IDLE_HOURS}" directly
in arithmetic, which can crash if the env var is non-integer; mirror the integer
validation used in check_tool_freshness by normalizing/validating
AIDEVOPS_TOOL_IDLE_HOURS into an integer (falling back to
DEFAULT_TOOL_IDLE_HOURS) before computing $((idle_threshold * 3600)), e.g.,
reuse the same parsing/regex or normalization logic from the
check_tool_freshness function so cmd_status uses a safe integer idle_threshold.
---
Nitpick comments:
In @.agents/scripts/auto-update-helper.sh:
- Around line 389-465: The code duplicates timestamp-parse/elapsed-check and
jq-based state updates across check_skill_freshness, check_openclaw_freshness,
check_tool_freshness and their update_*_check_timestamp helpers; extract that
logic into two helpers (e.g., _is_freshness_elapsed <state_key> <threshold_secs>
that reads STATE_FILE via jq, parses ISO timestamp into epoch (handle Darwin vs
Linux using date), computes elapsed and returns 0/1 plus elapsed in a variable,
and _update_check_timestamp <state_key> <count> that atomically updates/creates
STATE_FILE with jq setting the key to current UTC ISO timestamp and an optional
count field), then replace the duplicated blocks in check_skill_freshness (and
the other check_* functions) to call _is_freshness_elapsed before running checks
and call _update_check_timestamp at the end with the skill_updates value; keep
existing log messages and feature flags (AIDEVOPS_SKILL_AUTO_UPDATE,
AIDEVOPS_SKILL_FRESHNESS_HOURS) and continue to use skill-update-helper.sh
invocation unchanged.
- Around line 649-692: The loop parsing w output can treat the uptime summary
line as a user line when w -h is missing, causing parsed to remain 0 and
min_idle to be set to 0; inside the while read loop (which uses variables
min_idle, found_user, idle_field, parsed), add a guard to skip uptime-summary
lines before extracting idle_field — e.g. check and continue on lines matching
the uptime pattern like ^[[:space:]]*[0-9]+:[0-9]+[[:space:]]+up (or containing
" up " and "load average") so the uptime header is ignored and only real user
lines set found_user and parsed.
…idation
- Use GetSessionIdleTime instead of GetActiveTime for GNOME dbus idle
detection (GetActiveTime only measures screensaver runtime)
- Fix grep -c pipefail issue: use { grep || true; } subshell to avoid
producing '0\n0' when no lines match under set -o pipefail
- Validate idle_threshold in cmd_status to prevent arithmetic error
with invalid AIDEVOPS_TOOL_IDLE_HOURS values under set -e
🔍 Code Quality Report�[0;35m[MONITOR]�[0m Code Review Monitoring Report �[0;34m[INFO]�[0m Latest Quality Status: �[0;34m[INFO]�[0m Recent monitoring activity: 📈 Current Quality Metrics
Generated on: Sun Feb 22 16:03:27 UTC 2026 Generated by AI DevOps Framework Code Review Monitoring |
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|



Summary
auto-update-helper.sh— keeps all npm, brew, and pip tools installed bysetup.shup to date (OpenCode, gh, shellcheck, osgrep, MCP servers, etc.)Details
New functions in
auto-update-helper.shget_user_idle_seconds()check_tool_freshness()tool-version-check.sh --updateupdate_tool_check_timestamp()Idle detection strategy
ioreg -c IOHIDSystemHIDIdleTimexprintidle$DISPLAYdbus-sendGNOME ScreenSaverw -hsession idle parsing3:42,2days,23:15mformatsConfiguration
AIDEVOPS_TOOL_AUTO_UPDATEtruefalseto disableAIDEVOPS_TOOL_FRESHNESS_HOURS6AIDEVOPS_TOOL_IDLE_HOURS6Testing
statuscommand: shows tool check state + current idle time + eligibilityhelpcommand: updated with new env vars and workflow docsSummary by CodeRabbit