Claude/cpu guard review fixes dn d8u - #118
Conversation
The ladder previously hardcoded 3 tiers (strike==1 / strike==2 / else), so MAX_STRIKES had no effect — termination always fired on the 3rd hit regardless of configuration. Fix: replace `strikes == 2` with `strikes < MAX_STRIKES` so the STOP/CONT pause repeats for strikes 2..(MAX_STRIKES-1) and termination only triggers at strike >= MAX_STRIKES. All log and Telegram messages now include the current strike / total (e.g. "STRIKE3/5") for clarity. Reported by CodeAnt AI review of PR #116. https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
rw_cpu_guard.sh — v3 upgrade:
- --forensics [N] / --forensics=N mode merged from CPU.sh:
vmstat (steal time), iostat (disk wait), 1-second ps tracer
(catches sub-8s spikes), proc-count fork-storm detector, 10s
top snapshots — all collected in /root/rw_cpu_forensics/
- Prints a structured summary after collection: top offenders,
peak proc count, steal-time samples, guard ACT log tail
- Safe to run alongside the daemon simultaneously (passive only)
- FORENSICS_DIR and FORENSICS_DURATION env overrides added
- Header updated to v3; all usage docs updated
runewager_redeploy.sh — new one-shot master deploy script:
1. Stop runewager systemd service
2. Kill anything holding port 3000 (SIGTERM → SIGKILL)
3. npm ci at low priority (nice+ionice)
4. Install/restart rw_cpu_guard via --install
5. Start runewager systemd service
6. Health-check bot at /health (waits up to 30 s)
7. Launch 5-min background forensics trace (non-blocking)
8. Final status summary (services, port, load, memory,
guard ACT log, bot journal tail)
- --dry-run and --skip-forensics flags
- Colour output; VPS path fallback; no tooltips touched
https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
… checks rw_cpu_guard.sh: - Bug fix: proc_log sort/print was using field 2 (time HH:MM:SS) as the process count; changed to sort -k3 -rn and print $3 — correct since log format is "<date> <time> <count>" - Writable-path guard in _run_forensics(): fail fast with a clear message if FORENSICS_DIR cannot be created or written; suggests setting the FORENSICS_DIR env var as the fix runewager_redeploy.sh: - _check_deps(): preflight check for lsof and curl with install hint; called from main() before any steps run - _start_forensics(): writable-path check for the deploy log file; honours RW_FORENSICS_LOG env override; skips gracefully (with a suggestion) instead of silently redirecting to an unwritable path https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
Reviewer's GuideExtends rw_cpu_guard with a configurable strike ladder and a new passive CPU forensics mode, and adds a one-shot redeploy script that orchestrates bot restart, guard installation, health checks, and background forensics collection. Sequence diagram for runewager_redeploy one-shot nuclear redeploysequenceDiagram
actor Admin
participant Redeploy as RunewagerRedeployScript
participant Systemd
participant Guard as RwCpuGuardScript
participant Bot as RunewagerBotService
participant Net as Port3000
participant FxLog as ForensicsLog
Admin->>Redeploy: Run runewager_redeploy.sh [--dry-run][--skip-forensics]
Redeploy->>Redeploy: _check_root
Redeploy->>Redeploy: _check_deps (lsof, curl)
Redeploy->>Redeploy: _check_app_dir
Redeploy->>Systemd: systemctl stop runewager
Systemd-->>Redeploy: Service stopped (or was inactive)
Redeploy->>Net: lsof -t -i :3000
alt PIDs on port
Redeploy->>Net: kill -TERM PIDs
Redeploy->>Net: kill -KILL remaining PIDs
else Port already free
Net-->>Redeploy: no PIDs
end
Redeploy->>Redeploy: _npm_rebuild (cd app && nice+ionice npm ci)
Redeploy->>Guard: rw_cpu_guard.sh --install
Guard->>Systemd: Install/enable/start rw_cpu_guard service
Systemd-->>Guard: Guard active
alt systemd unit runewager.service exists
Redeploy->>Systemd: systemctl start runewager
else no systemd unit
Redeploy->>Redeploy: fallback to prod-run.sh (if present)
end
loop until healthy or timeout (<=30s)
Redeploy->>Bot: HTTP GET /health
Bot-->>Redeploy: HTTP 200 JSON or error
end
opt Forensics not skipped and not dry-run
Redeploy->>Guard: rw_cpu_guard.sh --forensics=300 &
Guard->>FxLog: Append forensics output
end
Redeploy->>Systemd: Query is-active runewager, rw_cpu_guard
Systemd-->>Redeploy: Active / inactive states
Redeploy->>Net: lsof -t -i :3000
Net-->>Redeploy: Current PIDs on port
Redeploy->>Redeploy: Print load, memory, guard ACT log tail, bot log tail
Redeploy-->>Admin: Final redeploy summary
Flow diagram for rw_cpu_guard forensics mode (_run_forensics)flowchart TD
Start([Start forensics])
GetDuration["Set duration from arg or FORENSICS_DURATION"]
SetDir["Set output dir to FORENSICS_DIR"]
CheckDir{"Can create and write to FORENSICS_DIR?"}
DirError[["Print error and return 1"]]
InitFiles["Init paths: cpu_trace.csv, vmstat.log, iostat.log, proc_count.log, top_cpu.log, snapshot.txt"]
Snapshot["Write system snapshot (uptime, loadavg, cpu, memory, cgroup) to snapshot.txt"]
StartVmstat["Start vmstat 1s loop -> vmstat.log (background)"]
CheckIostat{"iostat installed?"}
StartIostat["Start iostat -xz 1 -> iostat.log (background)"]
SkipIostat["Write 'iostat not installed' to iostat.log"]
StartTrace["Start 1s CPU tracer (ps | awk cpu>15%) -> cpu_trace.csv (background)"]
StartTop["Start 10s top-CPU ps snapshot -> top_cpu.log (background)"]
StartProc["Start 5s /proc process-count sampler -> proc_count.log (background)"]
ProgressLoop{{"elapsed < duration?"}}
Sleep10["sleep 10"]
PrintProgress["Print progress line with load and lines_traced"]
StopCollectors["kill vmstat, trace, top, proc, iostat (if running); wait"]
SummHeader["Print forensics summary header"]
SummCPU["Summarize top CPU offenders from cpu_trace.csv"]
SummProc["Summarize peak process counts from proc_count.log"]
SummSteal["Summarize last 5 vmstat steal-time samples"]
SummGuard["Show last ACT entries from rw_cpu_guard log"]
SummFooter["Print paths for full data and guard log"]
End([End forensics])
Start --> GetDuration --> SetDir --> CheckDir
CheckDir -- no --> DirError --> End
CheckDir -- yes --> InitFiles --> Snapshot
Snapshot --> StartVmstat --> CheckIostat
CheckIostat -- yes --> StartIostat --> StartTrace
CheckIostat -- no --> SkipIostat --> StartTrace
StartTrace --> StartTop --> StartProc --> ProgressLoop
ProgressLoop -- yes --> Sleep10 --> PrintProgress --> ProgressLoop
ProgressLoop -- no --> StopCollectors --> SummHeader
SummHeader --> SummCPU --> SummProc --> SummSteal --> SummGuard --> SummFooter --> End
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
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. 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughA new deployment orchestration script for Runewager bot redeploys is introduced, alongside forensics functionality enhancements to the CPU guard monitoring script. The redeploy script automates service stopping, dependency installation, and health verification. The guard script adds background system forensics collection capabilities with configurable duration. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 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 |
There was a problem hiding this comment.
Hey - I've found 3 issues, and left some high level feedback:
- In
_summary, theecho -e " ${_bold}Memory:${_reset} $(free -m | awk 'NR==2{printf "used=%sMB free=%sMB\n",$3,$4}')"line has conflicting double quotes inside the command substitution, which will break the script; switch the innerprintfstring to single quotes or escape the inner double quotes. - The health check and JSON pretty-printing rely on
curlandpython3 -m json.tool, but onlycurlis validated in_check_deps; consider either checking forpython3as well or guarding the pretty-print block so it degrades gracefully when Python is not installed.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `_summary`, the `echo -e " ${_bold}Memory:${_reset} $(free -m | awk 'NR==2{printf "used=%sMB free=%sMB\n",$3,$4}')"` line has conflicting double quotes inside the command substitution, which will break the script; switch the inner `printf` string to single quotes or escape the inner double quotes.
- The health check and JSON pretty-printing rely on `curl` and `python3 -m json.tool`, but only `curl` is validated in `_check_deps`; consider either checking for `python3` as well or guarding the pretty-print block so it degrades gracefully when Python is not installed.
## Individual Comments
### Comment 1
<location path="scripts/rw_cpu_guard.sh" line_range="651-653" />
<code_context>
+ fi
+
+ # ── 1-second CPU tracer (catches sub-8s spikes the guard daemon may miss) ─
+ echo "timestamp,pid,ppid,cpu%,mem%,cmd" > "$trace"
+ ( while true; do
+ ps -eo pid,ppid,pcpu,pmem,cmd --sort=-pcpu --no-headers 2>/dev/null \
+ | awk -v ts="$(date '+%F %T')" '$3+0 > 15 {
+ gsub(/,/, ";", $5);
</code_context>
<issue_to_address>
**issue (bug_risk):** The forensics CPU tracer is printing the wrong command column due to awk field indexing.
In this `ps` output, `$5` is the first token of `cmd` and `$6` is the second. Your change prints `$6` as the `cmd` column, so the first word of the command is dropped and the CSV no longer matches the header or later uses that assume it contains the full command (e.g., `substr($6,1,60)`). Instead, either print `$5` (after the `gsub`) or rebuild the full command field from `$5..$NF`, then apply `gsub(/,/, ";", cmd)` and print `cmd` in the last column.
</issue_to_address>
### Comment 2
<location path="scripts/rw_cpu_guard.sh" line_range="749-756" />
<code_context>
+ --status) mode="status" ;;
+ --once) mode="once" ;;
+ --dry-run) DRY_RUN="1" ;;
+ --forensics) mode="forensics" ;;
+ --forensics=*) mode="forensics"; FORENSICS_DURATION="${arg#*=}" ;;
--help|-h)
- grep '^#' "$SCRIPT_PATH" 2>/dev/null | head -30 | sed 's/^# *//'
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Consider validating FORENSICS_DURATION from --forensics=N to avoid non-numeric or pathological values.
`--forensics=*` currently just sets `FORENSICS_DURATION` and later uses it in arithmetic:
```bash
while (( elapsed < duration )); do
elapsed=$(( elapsed + 10 ))
...
done
```
Non-numeric or very large values (e.g. `--forensics=foo`) could cause arithmetic errors or unexpectedly long runs. Adding a simple numeric guard here would harden the mode:
```bash
--forensics=*)
mode="forensics"
FORENSICS_DURATION="${arg#*=}"
if ! [[ "$FORENSICS_DURATION" =~ ^[0-9]+$ ]]; then
echo "Invalid --forensics duration: $FORENSICS_DURATION (must be seconds)" >&2
exit 1
fi
;;
```
```suggestion
case "$arg" in
--install) mode="install" ;;
--status) mode="status" ;;
--once) mode="once" ;;
--dry-run) DRY_RUN="1" ;;
--forensics) mode="forensics" ;;
--forensics=*)
mode="forensics"
FORENSICS_DURATION="${arg#*=}"
if ! [[ "$FORENSICS_DURATION" =~ ^[0-9]+$ ]]; then
echo "Invalid --forensics duration: $FORENSICS_DURATION (must be an integer number of seconds)" >&2
exit 1
fi
;;
--help|-h)
```
</issue_to_address>
### Comment 3
<location path="scripts/runewager_redeploy.sh" line_range="363-364" />
<code_context>
+ esac
+ done
+
+ hdr "Runewager Nuclear Redeploy — $(date)"
+ echo -e " App dir : $(_app)"
+ echo -e " Guard : $GUARD_SCRIPT"
+ echo -e " Dry-run : $( (( DRY_RUN )) && echo YES || echo no )"
</code_context>
<issue_to_address>
**nitpick:** Initial "App dir" banner can be inconsistent with the later APP_DIR_OVERRIDE fallback.
Since `_check_app_dir` can later detect `/var/www/html/Runewager` and set `APP_DIR_OVERRIDE`, the banner may show an outdated app dir when the fallback is used. To avoid confusion, consider calling `_check_app_dir` before printing the banner, or re-printing the resolved app dir afterward so the displayed path matches what the script actually uses.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
All conflicts were between our reviewed/fixed HEAD and the older unpatched main version. Kept HEAD in all cases: rw_cpu_guard.sh: - Keep writable-path guard in _run_forensics() (vs bare mkdir -p) - Keep sort -k3 / $3 proc-count fix (vs buggy sort -k2 / $2) runewager_redeploy.sh: - Keep _check_deps() function (lsof/curl preflight check) - Keep _check_deps call in main() - Keep RW_FORENSICS_LOG override + writability check in _start_forensics() (vs hardcoded /var/log path) https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
Nitpicks 🔍
|
|
CodeAnt AI finished reviewing your PR. |
rw_cpu_guard.sh:
- Bug fix: CPU tracer awk now rebuilds full cmd from $5..$NF before
gsub so multi-word commands are not truncated to first token; the
gsub and printf now use the `cmd` variable — fixes mismatched CSV
header and later substr($6,…) reads
- Validate --forensics=N: rejects non-numeric and zero values with a
clear error message before any execution begins
runewager_redeploy.sh:
- Bug fix: double-quote conflict in _summary Memory line resolved by
extracting free|awk into a local variable (_mem) and interpolating
it into the echo-e separately — no more nested quote ambiguity
- Guard python3 in _health_check: check command -v python3 before
piping through json.tool; falls back to raw output when absent —
curl alone suffices for the health check itself
- Nitpick: _check_root/_check_deps/_check_app_dir now run before the
banner so the displayed "App dir" always shows the resolved path
(including the VPS fallback) rather than the pre-check default
- Bug fix: npm ci exit code was silently swallowed by the tail|sed
pipe; now captured via ${PIPESTATUS[0]} immediately after the pipe
and propagated — a failed install aborts the redeploy with a clear
message instead of proceeding silently
https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
User description
Summary by Sourcery
Add CPU forensics mode to the rw_cpu_guard daemon and introduce a one-shot scripted redeploy flow for the Runewager bot.
New Features:
Enhancements:
CodeAnt-AI Description
Add a one-shot redeploy script and passive CPU forensics; fix guard strike logic
What Changed
Impact
✅ Shorter redeploys with automated health checks✅ Clearer forensic reports for transient CPU spikes✅ Fewer unintended process terminations due to correct strike handling💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Summary by CodeRabbit
New Features
Chores