Files
dev/scripts/code-memory-guard.sh
T
zeekayandHanzo Dev 6cbbea2d03 merge: just-every/code v0.6.169 (e4fe007150) — keep Hanzo identity
Our history is just-every's with author emails rewritten, so the graphs are
disjoint and git finds no merge base. Supplied one by hand: d1f1f51a41, the
just-every commit matching our Oct-2025 fork point (22 files apart). 9618
upstream commits, 7004 files, +1.81M/-159k, 37 conflicts.

Resolution:
- Upstream code where our side was the Oct-2025 prototype of a feature they
  have since reimplemented 3-5x larger (agent_runs, browser_sessions,
  history_cell/{agent,browser}, the vt100 harness and its snapshots).
- Upstream's config.rs module split (builder/defaults/sources/validation)
  kept; zen5-coder and the provider-follows-model rule re-applied on top.
- Ours where the file IS the identity: README, package.json, postinstall,
  release notes pipeline, integration-zed.
- Hybrid where upstream improved a file we had branded: updates.rs (their
  release-repo migration, our hanzoai/dev), release.yml (their fail-fast npm
  auth check, our package name), chatwidget.rs (their turn handling, our
  HANZO_USER_KEY hint), exec human output (their 237 lines, our banner).

Superseded and dropped deliberately: our resume_command_name() coder-alias
hack — upstream's derive_resume_command_name() reads the invocation basename
generically, which yields "dev" for us.

LLM.md now records the real topology and the sync point; AGENTS.md and
CLAUDE.md are symlinks to it again. Single parent on purpose: adopting
jecode/main as a second parent would re-import 13,742 commits carrying the
upstream author emails a prior rewrite deliberately removed.

Version 0.2.188 -> 0.2.189.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-05 23:09:12 -07:00

89 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
INTERVAL_SEC=${INTERVAL_SEC:-5}
MATCH_UID=${MATCH_UID:-1000}
MATCH_REGEX=${MATCH_REGEX:-/code-rs/bin/code([[:space:]]|$)}
RSS_KB_LIMIT=${RSS_KB_LIMIT:-8388608}
PRESSURE_RSS_KB_LIMIT=${PRESSURE_RSS_KB_LIMIT:-4194304}
MEM_AVAILABLE_FLOOR_KB=${MEM_AVAILABLE_FLOOR_KB:-786432}
HARD_MEM_AVAILABLE_FLOOR_KB=${HARD_MEM_AVAILABLE_FLOOR_KB:-2097152}
TERM_GRACE_SEC=${TERM_GRACE_SEC:-10}
log() {
local message=$1
logger -t code-memory-guard -- "$message" || true
printf '%s %s\n' "$(date -Is)" "$message" >&2
}
mem_available_kb() {
awk '/MemAvailable:/ { print $2; exit }' /proc/meminfo
}
select_candidate() {
ps -eo pid=,uid=,rss=,args= --sort=-rss | awk \
-v guard_uid="$MATCH_UID" \
-v guard_regex="$MATCH_REGEX" '
$2 == guard_uid {
rss = $3
cmd = substr($0, index($0, $4))
if (cmd ~ guard_regex) {
print $1, rss, cmd
exit
}
}
'
}
terminate_pid() {
local pid=$1
local reason=$2
local rss_kb=$3
local cmd=$4
log "stopping pid=${pid} rss_kb=${rss_kb} reason=${reason} cmd=${cmd}"
kill -TERM "$pid" 2>/dev/null || return 0
local deadline=$((SECONDS + TERM_GRACE_SEC))
while kill -0 "$pid" 2>/dev/null; do
if (( SECONDS >= deadline )); then
break
fi
sleep 1
done
if kill -0 "$pid" 2>/dev/null; then
log "pid=${pid} survived SIGTERM; sending SIGKILL"
kill -KILL "$pid" 2>/dev/null || true
fi
}
main() {
log "starting guard uid=${MATCH_UID} rss_limit_kb=${RSS_KB_LIMIT} pressure_limit_kb=${PRESSURE_RSS_KB_LIMIT} mem_floor_kb=${MEM_AVAILABLE_FLOOR_KB} hard_floor_kb=${HARD_MEM_AVAILABLE_FLOOR_KB}"
while true; do
local available_kb
available_kb=$(mem_available_kb)
local candidate
candidate=$(select_candidate || true)
if [[ -n "$candidate" ]]; then
local pid rss_kb cmd
pid=${candidate%% *}
local rest=${candidate#* }
rss_kb=${rest%% *}
cmd=${rest#* }
if (( rss_kb >= RSS_KB_LIMIT && available_kb <= HARD_MEM_AVAILABLE_FLOOR_KB )); then
terminate_pid "$pid" "rss_limit_exceeded available_kb=${available_kb}" "$rss_kb" "$cmd"
elif (( available_kb <= MEM_AVAILABLE_FLOOR_KB && rss_kb >= PRESSURE_RSS_KB_LIMIT )); then
terminate_pid "$pid" "low_mem_available_kb=${available_kb}" "$rss_kb" "$cmd"
fi
fi
sleep "$INTERVAL_SEC"
done
}
main "$@"