Historical internal name "uncommonlisp" retired in favor of the
public name "lumbda" ahead of lumbda.com going live. Scope of
this commit:
Source files renamed:
uncommonlisp.py -> lumbda.py
asm/uncommonlisp.s -> asm/lumbda.s
c/uncommonlisp.h -> c/lumbda.h
whitepaper/uncommonlisp-whitepaper -> whitepaper/lumbda-whitepaper (.rst + .pdf)
Binaries renamed (tracked ones; c/ was always gitignored):
asm/uncommonlisp, asm/uncommonlisp-gc, asm/uncommonlisp.o,
asm/uncommonlisp-gc.o -> asm/lumbda(-gc)(.o)
c/.gitignore -> ignores lumbda
Internal string updates (sed pass ordered longest-first):
asm/uncommonlisp -> asm/lumbda
c/uncommonlisp -> c/lumbda
uncommonlisp.py -> lumbda.py
UNCOMMONLISP_BIN -> LUMBDA_BIN (asm/test.sh env var)
"uncommonlisp> " -> "lumbda> " (asm REPL prompt baked into binary)
UNCOMMONLISP -> LUMBDA (macros, comments)
uncommonlisp -> lumbda (prose)
Binary portal magic updated:
"ULPORTAL" -> "LUMBDAB1" # "Lumbda Binary v1"
Old portal files are not backward-compatible — this is a deliberate
break since it's the rename moment. S-expression portals already
carry their own ";; lumbda-portal v1" header and remain cleanly
versioned.
WHITEPAPER.pdf / WHITEPAPER.rst symlinks repointed to the renamed
files. Makefile's whitepaper target targets lumbda-whitepaper.pdf.
Not changed (intentional, separate phases):
- Filesystem directory /home/fox/git/uncommonlisp itself
(fox renames locally and the gitlab repo URL in a follow-up)
- tests.py hardcoded cwd=/home/fox/git/uncommonlisp
(matches the current on-disk location; will flip when the
directory rename ships)
- Git history (immutable; old commits still say uncommonlisp,
which is correct — that's what they were)
Verified:
137 asm no-GC + 137 asm GC + 571 Python + 83 C + 189 shared
functional tests all pass under the new names.
bench-gc-http (2000 req): all 4 cells behave as expected
(cells 1/2 flat, 3 leaks, 4 bounded at 1 chunk).
Python REPL, C REPL, asm REPL all start cleanly.
146 lines
6.1 KiB
Markdown
146 lines
6.1 KiB
Markdown
# Agent Blackops — Lumbda repo
|
|
|
|
This repo is operated by **agent blackops** — ml agent for fox/timehexon on the unsandbox/unturf/permacomputer platform. **Lumbda** is the language (home: lumbda.com); the repo directory and binaries still use the historical name `lumbda` until the filesystem rename ships in a later phase.
|
|
|
|
## 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
|
|
|
|
```bash
|
|
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 | `lumbda.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. Fox's machine has been crashed twice by
|
|
this: once on 2026-04-16 (19.3 GB RSS) and once on 2026-04-17. Both
|
|
times blackops spawned an asm server in the background for testing
|
|
and failed to verify it was gone before moving on. The first crash
|
|
added this discipline section; the second proved the discipline
|
|
needed teeth. Hence the MANDATORY checklist below.
|
|
|
|
**Shared-machine context:** other agents run on this box. An OOM
|
|
crash is not just "my problem" — it takes their state down too.
|
|
The rules below are belt, suspenders, AND a parachute so that even
|
|
if two safeguards fail, the kernel itself backstops.
|
|
|
|
**MANDATORY pattern — every asm/lumbda test in a shell block:**
|
|
|
|
```bash
|
|
set -e # (1) fail-fast
|
|
ulimit -v 524288 # (2) KERNEL CAP: 512 MB virt
|
|
# process gets SIGKILL at cap, no matter what
|
|
trap 'pkill -9 -u "$USER" -f "examples/http-server|asm/lumbda" 2>/dev/null || true' \
|
|
EXIT INT TERM # (3) cleanup always fires
|
|
|
|
timeout 30 asm/lumbda < server.lsp & # (4) wall-clock ceiling
|
|
SPID=$!
|
|
# ... do the work (curl requests, measurements, etc.) ...
|
|
kill -9 $SPID 2>/dev/null; wait $SPID 2>/dev/null # (5) explicit cleanup
|
|
|
|
# (6) VERIFY the block is clean before moving on
|
|
pgrep -u "$USER" -f 'asm/lumbda|examples/http-server' \
|
|
&& { echo "STRAGGLER"; exit 1; } || true
|
|
```
|
|
|
|
Six layers. Bypass any one and the next still catches. Two crashes
|
|
happened when I had only layers 3-5; the kernel cap (2) is what turns
|
|
"if I forget" from "fox reboots" into "my one rogue process dies at
|
|
512 MB without touching shared RAM."
|
|
|
|
Additional rules:
|
|
|
|
- `ulimit -v` affects only the shell it runs in and its children, so
|
|
it cannot degrade anyone else's agents. Always set it before
|
|
backgrounding any Lumbda process.
|
|
- Bound iterations **inside the .lsp** (e.g. `*max-requests* = 50000`
|
|
in `examples/http-server.lsp`). Never raise for long-running tests.
|
|
- Use `pkill -u "$USER" -f <pattern>` not `pkill` alone — others may
|
|
have their own processes on this machine.
|
|
- Prefer FOREGROUND runs when possible: `timeout 10 asm/lumbda
|
|
< test.lsp` with the `.lsp` exiting on its own beats backgrounding.
|
|
- C has Boehm GC via `GC_MALLOC`. Python has Python's GC. Asm has
|
|
neither. Risk scales with how long the asm process lives.
|
|
- If `ulimit` is unavailable (some container setups), use
|
|
`systemd-run --user --scope -p MemoryMax=512M -- asm/lumbda ...`
|
|
as the equivalent cgroup-based cap.
|
|
|
|
## MOAD Scanner
|
|
|
|
**`~/git/unmoad.com/` detects MOAD defects in source code.** Run it on every change.
|
|
|
|
```bash
|
|
cd ~/git/unmoadner && make all
|
|
./unmoad ~/git/lumbda/ # scan entire repo
|
|
./unmoad ~/git/lumbda/asm/ # scan assembly only
|
|
./unmoad ~/git/lumbda/c/ # scan C only
|
|
./unmoad ~/git/lumbda/*.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.
|