Skip to content

fix: prevent ShellCheck memory explosion with RSS watchdog, rate limiting, and PATH fix#3105

Closed
johnwaldo wants to merge 4 commits intomarcusquinn:mainfrom
johnwaldo:bugfix/shellcheck-memory-watchdog
Closed

fix: prevent ShellCheck memory explosion with RSS watchdog, rate limiting, and PATH fix#3105
johnwaldo wants to merge 4 commits intomarcusquinn:mainfrom
johnwaldo:bugfix/shellcheck-memory-watchdog

Conversation

@johnwaldo
Copy link
Contributor

@johnwaldo johnwaldo commented Mar 7, 2026

Summary

Fixes the recurring ShellCheck memory explosion that caused a system crash on Mar 7 (20 GB → 48 GB+ in minutes, 18.5 GB single shellcheck process).

Root cause analysis:

  • ulimit -v is a complete no-op on macOS ARM (setrlimit failed: invalid argument) — the wrapper's memory cap was doing nothing
  • The memory-pressure monitor polls every 60s, but shellcheck grows from 0 to 18 GB in under 60s
  • bash-language-server immediately respawns killed shellcheck processes, creating a kill-respawn-grow cycle
  • PATH shim was at the end of PATH in some contexts, so the real shellcheck was found first

Three-layer fix:

1. shellcheck-wrapper.sh — RSS watchdog + rate limiter

  • Background RSS watchdog replaces broken ulimit -v: polls child process RSS every 2s, kills at 1 GB
  • Respawn rate limiter with exponential backoff (5s → 10s → 20s → ... → 300s max) prevents kill-respawn-grow cycles — returns empty {"comments":[]} instead of running when in backoff
  • Hard timeout of 120s as additional safety net
  • All three work on macOS ARM (no ulimit -v dependency)

2. memory-pressure-monitor.sh v2.1.0 — faster detection

  • Lower thresholds: warn at 1 GB, kill at 2 GB (was 2/4 GB) — secondary defense behind wrapper's 1 GB limit
  • Faster polling: 30s launchd interval (was 60s), adaptive 10s when shellcheck detected
  • Fix zsh false positives: match patterns against command basename only, not full command line (eliminates ~2,880 false warnings/day from zsh -l -c opencode)
  • Lower shellcheck runtime: 5 min max (was 10 min) — wrapper has 120s timeout, so anything surviving 5 min bypassed the wrapper

3. setup-modules/shell-env.sh — PATH ordering fix

  • Strip existing ~/.aidevops/bin from PATH before prepending, guaranteeing first position
  • Previously could end up at the end of PATH, causing the real shellcheck to be found first

Testing

  • ShellCheck: zero violations on all 3 files (info level)
  • Existing test suite: all tests pass
  • Watchdog kill: verified with low timeout (1s) — correctly kills and records backoff
  • Rate limiter: verified with simulated backoff file — returns instantly with empty results
  • zsh false positive: verified — monitor no longer shows zsh processes
  • PATH ordering: verified via launchctl getenv PATH — shim dir is first

Crash timeline (from logs)

08:15:35  Kill shellcheck PID 37298 — 5,392 MB RSS
08:15:38  Kill shellcheck PID 37287 — 4,901 MB RSS
08:18:46  Kill shellcheck PID 44184 — 5,372 MB (respawned!)
08:19:51  Kill shellcheck PID 44383 — 18,570 MB RSS  ← 18.5 GB single process
08:19:53  Kill shellcheck PID 47766 — 9,403 MB RSS
08:19:56  Total: 31,075 MB across 22 processes, 8 sessions

With this fix, the wrapper would have killed each process at 1 GB (not 4 GB), and the rate limiter would have prevented the respawn cycle entirely.

Summary by CodeRabbit

  • New Features

    • Memory monitoring now adapts polling speed when ShellCheck is active for faster detection.
    • ShellCheck execution includes resource protection that automatically prevents excessive memory usage.
    • Rate limiting implemented to prevent rapid re-invocation after crashes.
  • Bug Fixes

    • Eliminated duplicate process entries in monitoring output.
    • Improved PATH handling on macOS to ensure correct tool versions are used.
  • Chores

    • Adjusted memory thresholds for improved resource management.

…ting, and PATH fix

Three defenses against the Mar 7 crash (18.5 GB shellcheck, 31 GB total):

shellcheck-wrapper.sh:
- Replace broken ulimit -v (no-op on macOS ARM — EINVAL) with background
  RSS watchdog that polls every 2s and kills at 1 GB RSS
- Add respawn rate limiter with exponential backoff (5s, 10s, 20s... 300s)
  to prevent kill-respawn-grow cycles from bash-language-server
- Add 120s hard timeout as additional safety net

memory-pressure-monitor.sh (v2.1.0):
- Lower thresholds: warn at 1 GB, kill at 2 GB (was 2/4 GB)
- Lower shellcheck runtime: 5 min (was 10 min)
- Fix zsh false positives: match MONITORED_PATTERNS against command
  basename only, not full command line with arguments
- Adaptive polling: 10s when shellcheck detected, 30s normal (was 60s)
- Launchd plist interval: 30s (was 60s)

setup-modules/shell-env.sh:
- Fix PATH ordering: strip existing shim_dir from PATH before prepending
  to guarantee ~/.aidevops/bin is FIRST, not appended at end
- Document ulimit -v macOS ARM limitation
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 7, 2026

Warning

Rate limit exceeded

@marcusquinn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 32 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3c5ed467-71ab-4f5c-b138-32e18b594439

📥 Commits

Reviewing files that changed from the base of the PR and between 64ac4c2 and cd9837c.

📒 Files selected for processing (3)
  • .agents/scripts/memory-pressure-monitor.sh
  • .agents/scripts/shellcheck-wrapper.sh
  • setup-modules/shell-env.sh

Walkthrough

This PR implements multi-layered resource guards for ShellCheck to prevent memory pressure incidents. Changes include adaptive process monitoring with dynamic polling intervals, RSS-based process termination with exponential backoff rate limiting, and robust PATH sanitization to ensure consistent wrapper invocation. Configuration thresholds are lowered across per-process limits and runtime constraints.

Changes

Cohort / File(s) Summary
ShellCheck Process Defense
.agents/scripts/shellcheck-wrapper.sh, .agents/scripts/memory-pressure-monitor.sh
Introduces three-layer defense: argument filtering, RSS watchdog that terminates processes exceeding memory limits with exponential backoff rate limiting (_check_rate_limit, _record_kill, _start_watchdog functions), and adaptive polling (10s when ShellCheck detected). Version bump to 2.1.0; per-process thresholds reduced (RSS_WARN from 2048→1024 MB, RSS_CRIT from 4096→2048 MB); improved process collection with PID deduplication and basename pattern matching.
Shell Environment Configuration
setup-modules/shell-env.sh
Adds preflight validation of shellcheck wrapper executable and functionality. Reworks macOS PATH preparation with sanitization logic that guarantees shim directory precedence, removing duplicate entries to prevent wrapper bypass. Updates LaunchAgent StartInterval from 60 to 30 seconds and install messaging to reflect new check cadence.

Sequence Diagram

sequenceDiagram
    participant Client as Invoker
    participant Wrapper as ShellCheck Wrapper
    participant RateLimit as Rate Limiter
    participant Watchdog as RSS Watchdog
    participant ShellCheck as Real ShellCheck
    participant Monitor as Memory Monitor

    Client->>Wrapper: shellcheck [args]
    Wrapper->>RateLimit: _check_rate_limit()
    alt Rate limit active
        RateLimit-->>Wrapper: return empty JSON
        Wrapper-->>Client: no-diagnostics response
    else Rate limit clear
        RateLimit-->>Wrapper: proceed
        Wrapper->>Wrapper: filter args (remove --external-sources)
        Wrapper->>Wrapper: apply ulimit -v constraint
        Wrapper->>ShellCheck: spawn background process
        Wrapper->>Watchdog: _start_watchdog(pid)
        par
            ShellCheck-->>ShellCheck: run analysis
            Watchdog->>Monitor: poll RSS periodically
            Monitor-->>Watchdog: current memory usage
            alt RSS > LIMIT or timeout elapsed
                Watchdog->>ShellCheck: kill process
                Watchdog->>RateLimit: _record_kill()
            end
        end
        Wrapper->>ShellCheck: wait for exit
        Wrapper->>Watchdog: terminate monitor
        ShellCheck-->>Wrapper: exit status & diagnostics
        Wrapper-->>Client: return ShellCheck output
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • #2855: Implements identical ShellCheck defensive controls (RSS watchdog, kill-on-RSS/timeout, exponential backoff rate limiting)
  • #2995: Modifies setup-modules/shell-env.sh with shellcheck wrapper shim validation and PATH sanitization logic
  • #2940: Adjusts memory-pressure-monitor.sh process collection and LaunchAgent polling intervals (30-second cadence)

Suggested labels

bug, external-contributor

Poem

🛡️ Three shields now guard the checker's might,
RSS watchdog keeps memory tight,
Backoff tames the restless flame,
PATH ensures the wrapper's claim,
Resource balance—our DevOps delight! ⚔️

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main changes: introducing an RSS watchdog, rate limiting, and PATH fix to prevent ShellCheck memory explosion.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello, 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 addresses critical system stability issues caused by ShellCheck memory explosions, particularly on macOS ARM where ulimit -v is ineffective. It introduces a robust, multi-layered defense system within the ShellCheck wrapper, enhances the system-wide memory pressure monitor for faster and more accurate detection, and corrects a PATH configuration problem to ensure these new protections are always active. The changes aim to prevent future system crashes and improve the reliability of ShellCheck operations.

Highlights

  • Enhanced ShellCheck Wrapper: Introduced an RSS watchdog to kill ShellCheck processes exceeding 1GB memory, implemented an exponential backoff rate limiter to prevent respawn cycles, and added a 120-second hard timeout, replacing the ineffective ulimit -v on macOS ARM.
  • Improved Memory Pressure Monitor: Lowered memory thresholds (1GB warn, 2GB kill), increased polling frequency (30s launchd interval, adaptive 10s when ShellCheck is detected), and fixed zsh false positives by matching patterns against command basenames only.
  • Corrected PATH Ordering: Ensured the ShellCheck wrapper's directory is always at the beginning of the system PATH by explicitly removing any existing occurrences before prepending, guaranteeing it's used instead of the real ShellCheck binary.
Changelog
  • .agents/scripts/memory-pressure-monitor.sh
    • Updated script comments to reflect the new primary defense mechanism in shellcheck-wrapper.sh.
    • Decreased default RSS warning and critical thresholds for processes.
    • Reduced the maximum runtime for ShellCheck processes.
    • Updated the process collection logic to match patterns against command basenames, avoiding false positives from zsh commands.
    • Implemented adaptive polling for the daemon mode, checking more frequently when ShellCheck processes are active.
    • Adjusted the launchd interval for the daemon from 60 seconds to 30 seconds.
  • .agents/scripts/shellcheck-wrapper.sh
    • Revised script comments to detail the new three-layer defense strategy.
    • Added new configuration variables for RSS limits, watchdog intervals, hard timeouts, and rate limiting.
    • Introduced a rate limiting mechanism with exponential backoff to prevent rapid respawning of killed processes.
    • Implemented a background RSS watchdog to actively monitor and kill ShellCheck processes exceeding a defined memory limit.
    • Modified the main execution flow to integrate rate limiting, ulimit -v (where effective), and the background RSS watchdog.
  • setup-modules/shell-env.sh
    • Updated comments to clarify the wrapper's use of an RSS watchdog.
    • Modified the setup_shellcheck_wrapper function to ensure the ~/.aidevops/bin directory is always prepended to the PATH, removing any existing occurrences to prevent incorrect ordering.
Activity
  • No human activity (comments, reviews, progress updates) has been recorded for this pull request.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a robust, multi-layered defense against the ShellCheck memory explosion issue, incorporating an RSS watchdog, respawn rate limiting, and a hard timeout in shellcheck-wrapper.sh. However, a critical Path Injection vulnerability was identified in setup-modules/shell-env.sh, where the PATH manipulation for launchctl can introduce a trailing colon, posing a significant security risk. Additionally, several instances of 2>/dev/null were identified that suppress potentially important errors, which has been addressed. A race condition in _record_kill was also noted. While the adaptive polling in memory-pressure-monitor.sh and the PATH ordering fix in setup-modules/shell-env.sh are positive improvements, further suggestions are provided to enhance the overall efficiency and robustness of the new shell scripts.

Comment on lines +152 to +164
# Record that a kill happened (called by the watchdog)
_record_kill() {
mkdir -p "$BACKOFF_DIR" 2>/dev/null || true

local kill_count=0
if [[ -f "$BACKOFF_FILE" ]]; then
read -r kill_count _ <"$BACKOFF_FILE" 2>/dev/null || kill_count=0
[[ "$kill_count" =~ ^[0-9]+$ ]] || kill_count=0
fi

kill_count=$((kill_count + 1))
printf '%s %s\n' "$kill_count" "$(date +%s)" >"$BACKOFF_FILE"
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The _record_kill function has a race condition. If multiple shellcheck processes are killed concurrently, their wrapper instances could call this function at the same time. The read-modify-write sequence on $BACKOFF_FILE is not atomic, which could lead to an incorrect kill_count and a shorter backoff period than intended, partially defeating the rate-limiting mechanism.

To fix this, you can use a lock to ensure the file update is atomic. A common and portable way to do this in shell is using mkdir as a lock.

Suggested change
# Record that a kill happened (called by the watchdog)
_record_kill() {
mkdir -p "$BACKOFF_DIR" 2>/dev/null || true
local kill_count=0
if [[ -f "$BACKOFF_FILE" ]]; then
read -r kill_count _ <"$BACKOFF_FILE" 2>/dev/null || kill_count=0
[[ "$kill_count" =~ ^[0-9]+$ ]] || kill_count=0
fi
kill_count=$((kill_count + 1))
printf '%s %s\n' "$kill_count" "$(date +%s)" >"$BACKOFF_FILE"
}
_record_kill() {
mkdir -p "$BACKOFF_DIR" || true
local lock_dir="${BACKOFF_DIR}/shellcheck.lock"
# Use mkdir for an atomic lock. If it fails, another process holds the lock.
if mkdir "$lock_dir" 2>/dev/null; then
# Ensure lock is removed on function exit
trap 'rmdir "$lock_dir" 2>/dev/null' RETURN
local kill_count=0
if [[ -f "$BACKOFF_FILE" ]]; then
read -r kill_count _ <"$BACKOFF_FILE" 2>/dev/null || kill_count=0
[[ "$kill_count" =~ ^[0-9]+$ ]] || kill_count=0
fi
kill_count=$((kill_count + 1))
printf '%s %s\n' "$kill_count" "$(date +%s)" >"$BACKOFF_FILE"
fi
}

Comment on lines +570 to +571
clean_path=$(printf '%s' "$PATH" | tr ':' '\n' | grep -v "^${shim_dir}$" | tr '\n' ':' | sed 's/:$//')
if launchctl setenv PATH "${shim_dir}:${clean_path}" 2>/dev/null; then

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The logic used to clean and prepend the shim directory to the PATH for launchctl setenv can introduce a trailing colon or a double colon. In shell PATH resolution, an empty entry (represented by a leading colon, a trailing colon, or two consecutive colons) is equivalent to the current directory (.). This is a security risk as it allows an attacker to place a malicious binary in a directory and have it executed if the user runs a command that is not found elsewhere in the PATH. If clean_path is empty (e.g., if PATH was empty or only contained shim_dir), the resulting PATH will be ${shim_dir}:. Additionally, suppressing stderr with 2>/dev/null can mask important errors.

Suggested change
clean_path=$(printf '%s' "$PATH" | tr ':' '\n' | grep -v "^${shim_dir}$" | tr '\n' ':' | sed 's/:$//')
if launchctl setenv PATH "${shim_dir}:${clean_path}" 2>/dev/null; then
local clean_path
clean_path=$(printf '%s' "$PATH" | tr ':' '\n' | grep -v "^${shim_dir}$" | tr '\n' ':' | sed 's/:$//')
if [[ -n "$clean_path" ]]; then
if launchctl setenv PATH "${shim_dir}:${clean_path}"; then
print_info "Prepended $shim_dir to PATH via launchctl (GUI processes)"
fi
else
if launchctl setenv PATH "${shim_dir}"; then
print_info "Set PATH to $shim_dir via launchctl (GUI processes)"
fi
fi
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

# 1st kill: 5s, 2nd: 10s, 3rd: 20s, ... up to MAX_BACKOFF (300s).
# Resets after MAX_BACKOFF seconds of no kills.
_check_rate_limit() {
mkdir -p "$BACKOFF_DIR" 2>/dev/null || true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using 2>/dev/null with mkdir -p suppresses potentially important errors, such as 'Permission denied'. If the backoff directory cannot be created, the rate-limiting feature will fail silently. This practice is also discouraged by the project's general rules.

Consider removing 2>/dev/null to make such errors visible for debugging. The || true will still prevent the script from exiting due to set -e.

This also applies to line 154 in _record_kill.

Suggested change
mkdir -p "$BACKOFF_DIR" 2>/dev/null || true
mkdir -p "$BACKOFF_DIR" || true
References
  1. Avoid using '2>/dev/null' for blanket suppression of command errors in shell scripts to ensure that authentication, syntax, or system issues remain visible for debugging.

@marcusquinn
Copy link
Owner

This PR is from an external contributor (@johnwaldo). Auto-merge is disabled for external PRs — a maintainer must review and merge manually.

@marcusquinn marcusquinn added the external-contributor PR from external contributor, requires maintainer review label Mar 7, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 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/shellcheck-wrapper.sh:
- Around line 33-35: The three environment tunables RSS_LIMIT_MB,
WATCHDOG_INTERVAL, and HARD_TIMEOUT are used directly in arithmetic, sleep and
numeric comparisons and must be validated; add a small validation routine (e.g.,
validate_positive_int) that checks each of these variables (readonly
RSS_LIMIT_MB, WATCHDOG_INTERVAL, HARD_TIMEOUT) against a strict integer/positive
regex or integer parse, coerce or replace non-numeric/zero values with safe
defaults (1024, 2, 120 respectively) and log a warning, and clamp excessively
small values (e.g., WATCHDOG_INTERVAL >= 1) before any use in $(( )), sleep or
-gt comparisons to avoid tight loops or premature aborts; call this validation
early (immediately after the readonly assignments) so all later watchdog logic
uses the sanitized values.

In `@setup-modules/shell-env.sh`:
- Around line 559-572: The PATH sanitization you added for macOS launchctl
doesn't update existing interactive/login shells; update the rc-file layer(s)
that currently add a presence-only guard (e.g., the code that sets PATH in
.zshenv/.bashrc/.profile and the fish config) to reuse the same
sanitize-and-prepend logic used with shim_dir/wrapper_path: compute a clean_path
by splitting $PATH, removing any exact occurrences of shim_dir (or
"$HOME/.aidevops/bin"), then export PATH as shim_dir followed by the cleaned
rest (preserving the empty-case), and for fish use string match -v to build PATH
similarly; ensure you reference the same shim_dir variable name and keep the
launchctl setenv SHELLCHECK_PATH/wrapper_path logic unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3d21c565-374d-454c-88ff-097a91fdec51

📥 Commits

Reviewing files that changed from the base of the PR and between 76b7d03 and 64ac4c2.

📒 Files selected for processing (3)
  • .agents/scripts/memory-pressure-monitor.sh
  • .agents/scripts/shellcheck-wrapper.sh
  • setup-modules/shell-env.sh

… fix PATH security

Address CHANGES_REQUESTED review from CodeRabbit and Gemini Code Assist:

shellcheck-wrapper.sh:
- Add _validate_int() to sanitize RSS_LIMIT_MB, WATCHDOG_INTERVAL, HARD_TIMEOUT
  before use in arithmetic/sleep (prevents tight loops from typos like 'abc')
- Fix race condition in _record_kill() with mkdir-based atomic lock
- Remove blanket 2>/dev/null from mkdir -p (surface permission errors)
- Add explicit return 0 to _record_kill()

setup-modules/shell-env.sh:
- Fix PATH trailing colon security issue in launchctl setenv (empty clean_path
  produced 'shim_dir:' which resolves '.' — PATH injection vector)
- Replace presence-only case guard with sanitize-and-prepend logic that strips
  existing shim_dir from PATH before prepending (fixes upgrade path where shim
  was appended at end, bypassing wrapper in new shells)
- Clean up stale old-form case-guard entries from .zshenv and rc files
- Update fish shell PATH line to use same sanitize-and-prepend pattern

CI failures (SonarCloud, Label PR, Monitor) are all fork permission issues
(403 'Resource not accessible by integration') — expected for external PRs.
@marcusquinn
Copy link
Owner

Worker killed after 6h43m with 0 commits (struggle_ratio: 17907). Thrashing detected — re-dispatching with fresh context. The worker was unable to make progress on the CI failures and review feedback.

@marcusquinn
Copy link
Owner

Worker killed after 9+ hours with struggle_ratio 9310 (18621 messages, 2 commits). Severe thrashing — worker was looping on review feedback without making progress. Re-dispatching with fresh context.

@marcusquinn
Copy link
Owner

@coderabbitai review

All review feedback has been addressed in commits 55fff8e, 495dc96, and cd9837c:

  1. Validate watchdog tunables (shellcheck-wrapper.sh) -- Added _validate_int() with min bounds (128/1/10) to prevent tight loops from invalid env vars
  2. PATH fix sticky for rc-file layers (shell-env.sh) -- Sanitize-and-prepend logic (_aidevops_shim) now used in .zshenv, all shell rc files, and fish config; old case guard entries cleaned up
  3. Race condition in _record_kill -- Added mkdir atomic lock
  4. PATH trailing colon security -- Empty-PATH guard prevents trailing colon (PATH injection vector)
  5. Remove 2>/dev/null from mkdir -p -- Stderr no longer suppressed on directory creation
  6. Docstring coverage -- Added docstrings to all functions (80%+ threshold)

ShellCheck: zero violations on all 3 files.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 7, 2026

@marcusquinn: Thank you for the thorough summary — the six addressed items look like solid, security-conscious hardening for this fix:

  • _validate_int() with enforced min bounds will prevent the tight-loop risk from malformed env vars.
  • The atomic mkdir lock in _record_kill correctly closes the TOCTOU race.
  • The empty-PATH guard for trailing colon is an important injection vector mitigation.
  • Sticky sanitize-and-prepend across .zshenv, rc files, and fish config ensures the shim ordering is reliably enforced at every shell entry point.

Triggering a fresh review of the latest commits now.


🧠 Learnings used
Learnt from: marcusquinn
Repo: marcusquinn/aidevops PR: 0
File: :0-0
Timestamp: 2026-03-03T16:33:18.313Z
Learning: For the marcusquinn/aidevops repository: The daily quality sweep system (pulse-wrapper.sh) should only mention coderabbitai for full codebase review when there are significant changes (Quality Gate failure, +10 issues in one day, etc.), not on every automated sweep with stable metrics.

Learnt from: alex-solovyev
Repo: marcusquinn/aidevops PR: 0
File: :0-0
Timestamp: 2026-03-04T05:50:49.615Z
Learning: In the marcusquinn/aidevops repository: As of 2026-03-04, the chrome-webstore-helper.sh SC2119/SC2120 (load_credentials argument mismatch) and stash-audit-helper.sh SC2181 (indirect exit code checking) ShellCheck issues have been resolved. ShellCheck now reports 0 errors and 0 warnings for these files.

Learnt from: CR
Repo: marcusquinn/aidevops PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-21T06:56:37.192Z
Learning: Applies to .agents/scripts/**/*.sh : Run ShellCheck on all shell scripts before committing
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@marcusquinn
Copy link
Owner

Closing in favor of a new PR from the rebased branch on origin. The fork branch was based on an older main, causing stale version/planning file diffs. All review feedback from CodeRabbit and Gemini Code Assist has been addressed. The new PR will have a clean diff with only the 3 relevant files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor PR from external contributor, requires maintainer review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants