lumbda/CLAUDE.md
russell@unturf.com 477bd5f7cd guardrails: bound http server, trap+cleanup bench, asm-no-GC in CLAUDE.md
Prevent recurrence of 2026-04-16 incident where a leaked asm HTTP
server grew to 19.3 GB RSS and crashed the machine.

examples/http-server.lsp:
- Adds *max-requests* = 50000 hard ceiling. Server self-terminates
  before unbounded heap growth reaches dangerous levels.
- Loop tracks request count, exits cleanly + closes server socket.

tests/web-benchmark.sh:
- SPAWNED_PIDS array tracks every background process.
- EXIT/INT/TERM trap kills them all (SIGTERM then SIGKILL).
- stop_server does SIGTERM with 500ms grace period then SIGKILL.
- Final straggler check via pgrep narrows to actual HTTP server
  processes (not shell/tmux with "uncommonlisp" in the name).
- pkill -9 fallback as belt-and-suspenders.

CLAUDE.md:
- New "Asm memory discipline" section documents the bump allocator
  leak behavior and the required operational discipline.
- Test counts updated (571 py + 83 c + 132 asm + 189 shared = 975).
2026-04-16 19:38:34 -04:00

4.2 KiB

Agent Blackops

This repo is operated by agent blackops — ml agent for fox/timehexon on the unsandbox/unturf/permacomputer platform.

Identity

Full shard: ~/git/unsandbox.com/blackops/BLACKOPS.md

Rules

  • I propose, fox decides. Unsure = ask. Can't ask = stop.
  • No autonomous ops decisions. No destructive commands without explicit instruction.
  • Fail-closed. Cleanup crew, not demolition.
  • Check the time every session. Gaps are information.
  • DRY in context — single source of truth, no sprawl.
  • Never say "AI" — always say "machine learning."
  • Prefer "defect" over "bug."

Orientation

date -u
pwd
git log --oneline -5
git status

Then ask fox what the mission is.

Documentation

  • A diagram is worth 10,000 words.russell@unturf.com
  • Architecture diagrams live in docs/*.dot (Graphviz DOT format)
  • Generate PNGs: make docs
  • Every implementation (Python, C, Assembly) has its own architecture diagram
  • When explaining architecture, create or reference a dot diagram first

Implementations

Impl Path Build Test REPL
Python uncommonlisp.py make test make repl
C c/ make c-build make c-test make c-repl
Assembly asm/ make asm-build make asm-test make asm-repl
All make test-all

Test Suites

  • Python unit/integration: tests.py (571 tests)
  • C unit/integration/JIT/continuations/portal: c/test.c (83 tests)
  • Assembly unit/integration/functional: asm/test.sh (132 tests)
  • Shared functional: tests/functional.lsp (189 tests, runs in Python + C)
  • Cross-impl portal matrix: tests/portal-cross-test.sh (9 cells)
  • Portal benchmark: tests/portal-benchmark.sh (timings + mismatch classification)
  • Web benchmark: tests/web-benchmark.sh (all three impls + Python http.server + busybox)
  • Total: 975 verified assertions via make test-all

Asm memory discipline — the heap does not shrink

The asm implementation uses a bump allocator (r15). Every allocation (string-append, tcp-recv, make-pair, number->string, etc.) grows r15 monotonically. When r15 hits r13 (heap limit), heap_grow mmaps ANOTHER 64 MB chunk. Nothing is ever freed.

A long-running asm server leaks ~64 MB every few thousand requests until it OOMs the machine. This actually crashed fox's machine on 2026-04-16 — a benchmark server grew to 19.3 GB RSS / 30 GB virt.

Never leave an asm server running in the background. Specifically:

  • Every background spawn in a bench script gets an EXIT trap: trap 'kill ${PIDS[@]} 2>/dev/null' EXIT
  • For sustained-throughput benchmarks, bound iterations inside the .lsp (e.g., (if (> n 1000) (exit 0) (loop (+ n 1)))) — never rely on external kill signals alone.
  • Before declaring a session done, verify: ps -u fox -o pid,rss,cmd | grep uncommonlisp | grep -v grep (no output = clean)
  • C has Boehm GC via GC_MALLOC. Python has Python's GC. Asm has neither. Risk scales with how long the asm process lives.

MOAD Scanner

~/git/unmoad.com/ detects MOAD defects in source code. Run it on every change.

cd ~/git/unmoadner && make all
./unmoad ~/git/uncommonlisp/          # scan entire repo
./unmoad ~/git/uncommonlisp/asm/      # scan assembly only
./unmoad ~/git/uncommonlisp/c/        # scan C only
./unmoad ~/git/uncommonlisp/*.py      # scan Python only

MANDATORY before committing new code: run unmoad on changed files. Machine learning agents (including blackops) propagate MOAD-0001 by default. The training data encodes O(N) linear scans as the norm. The scanner catches what our weights miss.

Supported languages for this repo: Python, C, Scheme (.lsp), Assembly (.s).

Key MOAD-0001 patterns the scanner catches:

  • Python: .count(), .index(), in list inside loops
  • C: std::find(), strcmp() inside loops
  • Scheme: (member), (memq), (assoc) inside (let loop), (for-each), (map)
  • Assembly: rep cmpsb inside search loops

The commit history of this repo proves the need: blackops wrote MOAD-0001 into fresh code on April 13-14 despite having full MOAD context. Fixed only after explicit audit on April 15. See whitepaper Section 14.